package com.ecep.contract.controller.project;

import java.text.NumberFormat;
import java.time.LocalDateTime;

import com.ecep.contract.controller.project.cost.ProjectCostWindowController;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.Project;
import com.ecep.contract.model.ProjectCost;
import com.ecep.contract.model.ProjectCostItem;
import com.ecep.contract.service.ContractItemService;
import com.ecep.contract.service.ProjectCostItemService;
import com.ecep.contract.service.ProjectCostService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.ProjectCostItemViewModel;
import com.ecep.contract.vm.ProjectCostViewModel;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.NumberStringConverter;
import lombok.Setter;

@FxmlPath("/ui/project/project-tab-cost.fxml")
public class ProjectTabSkinCost
        extends AbstProjectTableTabSkin<ProjectCost, ProjectCostViewModel>
        implements TabSkin {

    public TableColumn<ProjectCostViewModel, Number> idColumn;
    public TableColumn<ProjectCostViewModel, Employee> applicantColumn;
    public TableColumn<ProjectCostViewModel, LocalDateTime> applyTimeColumn;
    public TableColumn<ProjectCostViewModel, Employee> authorizerColumn;
    public TableColumn<ProjectCostViewModel, LocalDateTime> authorizationTimeColumn;

    public TableColumn<ProjectCostViewModel, Number> grossProfitMarginColumn;
    public TableColumn<ProjectCostViewModel, Number> inTaxAmountColumn;
    public TableColumn<ProjectCostViewModel, Number> inExclusiveTaxAmountColumn;
    public TableColumn<ProjectCostViewModel, Number> outTaxAmountColumn;
    public TableColumn<ProjectCostViewModel, Number> outExclusiveTaxAmountColumn;
    public TableColumn<ProjectCostViewModel, Number> versionColumn;

    public TableColumn<ProjectCostViewModel, String> descriptionColumn;

    @Setter
    private ProjectCostService costService;
    @Setter
    private ProjectCostItemService costItemService;
    @Setter
    private ContractItemService contractItemService;

    public ProjectTabSkinCost(ProjectWindowController controller) {
        super(controller);
    }

    @Override
    protected ProjectCostService getViewModelService() {
        return getCostService();
    }

    private ProjectCostService getCostService() {
        if (costService == null) {
            costService = getBean(ProjectCostService.class);
        }
        return costService;
    }

    private ProjectCostItemService getCostItemService() {
        if (costItemService == null) {
            costItemService = getBean(ProjectCostItemService.class);
        }
        return costItemService;
    }

    private ContractItemService getContractItemService() {
        if (contractItemService == null) {
            contractItemService = getBean(ContractItemService.class);
        }
        return contractItemService;
    }

    @Override
    public Tab getTab() {
        return controller.costTab;
    }

    @Override
    public void initializeTable() {
        super.initializeTable();
        idColumn.setCellValueFactory(param -> param.getValue().getId());

        applicantColumn.setCellValueFactory(param -> param.getValue().getApplicant());
        applicantColumn.setCellFactory(cell -> new EmployeeTableCell<>());
        applyTimeColumn.setCellValueFactory(param -> param.getValue().getApplyTime());
        applyTimeColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
        authorizerColumn.setCellValueFactory(param -> param.getValue().getAuthorizer());
        authorizerColumn.setCellFactory(cell -> new EmployeeTableCell<>());
        authorizationTimeColumn.setCellValueFactory(param -> param.getValue().getAuthorizationTime());
        authorizationTimeColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());

        inTaxAmountColumn.setCellValueFactory(param -> param.getValue().getInTaxAmount());
        inTaxAmountColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));
        inExclusiveTaxAmountColumn.setCellValueFactory(param -> param.getValue().getInExclusiveTaxAmount());
        inExclusiveTaxAmountColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));
        outTaxAmountColumn.setCellValueFactory(param -> param.getValue().getOutTaxAmount());
        outTaxAmountColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));
        outExclusiveTaxAmountColumn.setCellValueFactory(param -> param.getValue().getOutExclusiveTaxAmount());
        outExclusiveTaxAmountColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));

        grossProfitMarginColumn.setCellValueFactory(param -> param.getValue().getGrossProfitMargin());
        NumberFormat numberInstance = NumberFormat.getNumberInstance(getLocale());
        numberInstance.setMaximumFractionDigits(2);
        numberInstance.setMinimumFractionDigits(2);
        grossProfitMarginColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter(numberInstance)));

        versionColumn.setCellValueFactory(param -> param.getValue().getVersion());
        descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());

        Platform.runLater(() -> {
            table.getSortOrder().add(versionColumn);
        });
    }


    @Override
    protected ProjectCostViewModel createNewViewModel() {
        ProjectCostViewModel model = new ProjectCostViewModel();
        Project project = getParent();
        model.getProject().set(project);
        ProjectCost latest = getCostService().findLatestByProject(project);
        if (latest != null) {
            model.getVersion().set(latest.getVersion() + 1);
        } else {
            model.getVersion().set(1);
        }
        model.getStampTax().set(0.03f);
        model.getTaxAndSurcharges().set(11);
        model.getApplicant().set(project.getApplicant());
        model.getApplyTime().set(LocalDateTime.now());
        saveRow(model);
        return model;
    }

    @Override
    protected void onTableRowDoubleClickedAction(ProjectCostViewModel item) {
        showInOwner(ProjectCostWindowController.class, item);
    }

    @Override
    protected void createContextMenu(ContextMenu contextMenu) {
        super.createContextMenu(contextMenu);

        MenuItem menuItem = new MenuItem("复制");
        menuItem.setOnAction(this::onTableCopyAction);
        menuItem.visibleProperty().bind(table.getSelectionModel().selectedItemProperty().isNotNull());
        contextMenu.getItems().add(menuItem);
    }

    private void onTableCopyAction(ActionEvent event) {
        ProjectCostViewModel selectedItem = table.getSelectionModel().getSelectedItem();

        ProjectCost selectedCost = loadRowData(selectedItem);
        ProjectCost projectCost = new ProjectCost();
        selectedItem.copyTo(projectCost);
        projectCost.setId(null);
        projectCost.setVersion(selectedItem.getVersion().get() + 1);
        projectCost.setApplyTime(LocalDateTime.now());
        projectCost = saveRowData(projectCost);


        ProjectCostItemService costItemService = getCostItemService();
        for (ProjectCostItem selectedCostItem : costItemService.findByCost(selectedCost)) {
            ProjectCostItem item = new ProjectCostItem();
            ProjectCostItemViewModel.from(selectedCostItem).copyTo(item);
            item.setId(null);
            item.setCost(projectCost);
            costItemService.save(item);
        }

        ProjectCostViewModel model = new ProjectCostViewModel();

        model.update(projectCost);
        dataSet.add(model);
        saveRow(model);

    }
}
