package com.ecep.contract.controller.project;

import java.time.LocalDate;
import java.util.Objects;
import java.util.function.Consumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.ecep.contract.Desktop;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.Project;
import com.ecep.contract.model.ProjectSaleType;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.service.SaleTypeService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.ProjectViewModel;

import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import javafx.util.converter.NumberStringConverter;

@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/project/apply-new-project.fxml")
public class ApplyNewProjectWindowController extends BaseController {
    @Autowired
    private ProjectService projectService;
    @Autowired
    private SaleTypeService saleTypeService;
    @Autowired
    private EmployeeService employeeService;


    public ComboBox<ProjectSaleType> saleTypeComboBox;
    public TextField codeYearField;
    public Label codeYearLabel;

    public TextField codeSequenceNumberField;
    public Label codeSequenceNumberLabel;

    public Label codePreviewLabel;
    public Label codeLabel;

    public Label applicantLabel;

    public Button cancelBtn;
    public Button applyBtn;


    private ProjectViewModel viewModel = new ProjectViewModel();
    private ObjectProperty<Consumer<Project>> onApplied = new SimpleObjectProperty<>();

    public void setOnApplied(Consumer<Project> onApplied) {
        this.onApplied.set(onApplied);
    }

    @Override
    public Stage show(FXMLLoader loader, Window owner, Modality modality) {
        return super.show(loader, owner, Modality.APPLICATION_MODAL);
    }

    @Override
    public void onShown(WindowEvent windowEvent) {
        super.onShown(windowEvent);
        getTitle().set("申请新项目编号");

        viewModel.getCodeYear().set(25);

        initializeSaleTypeField(saleTypeComboBox);


        NumberStringConverter stringConverter = new NumberStringConverter();
        Bindings.bindBidirectional(codeYearField.textProperty(), viewModel.getCodeYear(), stringConverter);

        Bindings.bindBidirectional(codeSequenceNumberField.textProperty(), viewModel.getCodeSequenceNumber(), stringConverter);
        initializeApplicantLabel(applicantLabel);
        initializeCodePreviewLabel(codePreviewLabel);

        cancelBtn.setOnAction(event -> {
            cancelBtn.getScene().getWindow().hide();
        });


        applyBtn.disableProperty().bind(viewModel.getSaleType().isNull());
        applyBtn.setOnAction(event -> {
            Project newProject = new Project();
            newProject.setCodeYear(viewModel.getCodeYear().get());
            int codeSequenceNumber = viewModel.getCodeSequenceNumber().get();
            if (codeSequenceNumber == 0) {
                codeSequenceNumberLabel.setText("项目序号不能为0");
                codeSequenceNumberLabel.setStyle("-fx-text-fill: #ffa2a2");
                return;
            } else {
                codeSequenceNumberLabel.setText("");
                codeSequenceNumberLabel.setStyle("");
            }


            newProject.setCodeSequenceNumber(codeSequenceNumber);
            newProject.setSaleType(viewModel.getSaleType().get());

            Project exist = projectService.findBySaleTypeAndCodeYearAndCodeSequenceNumber(newProject.getSaleType(), newProject.getCodeYear(), newProject.getCodeSequenceNumber());
            if (exist != null) {
                codeLabel.setText("项目编号已存在");
                codeLabel.setStyle("-fx-text-fill: #ffa2a2");
                return;
            } else {
                codeLabel.setText("");
                codeLabel.setStyle("");
            }

            // 暂时的项目编号
            newProject.setCode(codePreviewLabel.getText());

            newProject.setApplicant(viewModel.getApplicant().get());
            newProject.setCreated(LocalDate.now());
            Project saved = projectService.save(newProject);
            Consumer<Project> consumer = onApplied.get();
            if (consumer != null) {
                consumer.accept(saved);
            }
            applyBtn.getScene().getWindow().hide();
        });

    }

    private void initializeApplicantLabel(Label applicantLabel) {
        Employee operator = employeeService.findById(Desktop.instance.getActiveEmployeeId());
        viewModel.getApplicant().set(operator);

        applicantLabel.textProperty().bind(Bindings.createObjectBinding(() -> {
            Employee employee = viewModel.getApplicant().get();
            if (employee == null) {
                return "- 异常，未取得当前操作员信息 -";
            }
            return employee.getName();

        }, viewModel.getApplicant()));
    }

    private void initializeCodePreviewLabel(Label codePreviewLabel) {
        codePreviewLabel.textProperty().bind(Bindings.createObjectBinding(() -> {
            StringBuilder sb = new StringBuilder();
            ProjectSaleType saleType = viewModel.getSaleType().get();
            if (saleType == null) {
                return "";
            }
            sb.append(saleType.getCode());


            int year = viewModel.getCodeYear().get();
            if (year < 10) {
                sb.append("0");
            }
            sb.append(year);

            int sn = viewModel.getCodeSequenceNumber().get();
            if (sn < 10) {
                sb.append("00");
            } else if (sn < 100) {
                sb.append("0");
            }
            sb.append(sn);
            return sb.toString();
        }, viewModel.getSaleType(), viewModel.getCodeYear(), viewModel.getCodeSequenceNumber()));
    }

    private void initializeSaleTypeField(ComboBox<ProjectSaleType> field) {
        ObservableList<ProjectSaleType> list = FXCollections.observableArrayList();
        saleTypeService.findAll().stream().filter(ProjectSaleType::isActive).forEach(list::add);
        field.setItems(list);
        field.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            viewModel.getSaleType().set(newValue);
            // 当 SequenceNumber 为 0 时， 自动检索最新的 SequenceNumber
            if (viewModel.getCodeYear().get() != 0) {
                int nextCodeSequenceNumber = projectService.getNextCodeSequenceNumber(newValue, viewModel.getCodeYear().get());
                viewModel.getCodeSequenceNumber().set(nextCodeSequenceNumber);
            }
        });
        EntityStringConverter<ProjectSaleType> converter = new EntityStringConverter<>();
        converter.setInitialized(saleType -> {
            return list.stream().filter(v -> v != null && Objects.equals(v.getId(), saleType.getId())).findFirst().orElse(null);
        });
        converter.setFromString(name -> {
            return list.stream().filter(v -> v != null && Objects.equals(v.getName(), name)).findFirst().orElse(null);
        });
        field.setConverter(converter);
        field.valueProperty().bindBidirectional(viewModel.getSaleType());

    }
}
