package com.ecep.contract.controller.tab;

import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.contract.sale_order.SalesOrderWindowController;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.service.SaleOrdersService;
import com.ecep.contract.service.SalesBillVoucherService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.SalesBillVoucherViewModel;
import com.ecep.contract.vm.SalesOrderViewModel;
import com.ecep.contract.vo.ContractItemVo;
import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.vo.SalesBillVoucherVo;
import com.ecep.contract.vo.SalesOrderVo;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.util.Callback;
import javafx.util.Duration;
import lombok.Setter;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.function.Function;
import java.util.stream.Collectors;

@FxmlPath("/ui/contract/sale-orders-tab-bill-voucher.fxml")
public class SalesOrderTabSkinBillVoucher
        extends
        AbstEntityTableTabSkin<SalesOrderWindowController, SalesOrderVo, SalesOrderViewModel, SalesBillVoucherVo, SalesBillVoucherViewModel>
        implements TabSkin {

    @Setter
    SaleOrdersService saleOrdersService;
    @Setter
    SalesBillVoucherService billVoucherService;
    @Setter
    private EmployeeStringConverter employeeStringConverter;

    /* 以下是合同内容 */
    public TableColumn<SalesBillVoucherViewModel, Number> itemTable_idColumn;
    public TableColumn<SalesBillVoucherViewModel, String> refIdColumn;
    public TableColumn<SalesBillVoucherViewModel, String> codeColumn;
    public TableColumn<SalesBillVoucherViewModel, Integer> employeeColumn;
    public TableColumn<SalesBillVoucherViewModel, Integer> makerColumn;
    public TableColumn<SalesBillVoucherViewModel, Integer> verifierColumn;

    public TableColumn<SalesBillVoucherViewModel, LocalDateTime> makerDateColumn;
    public TableColumn<SalesBillVoucherViewModel, LocalDateTime> verifierDateColumn;
    public TableColumn<SalesBillVoucherViewModel, LocalDateTime> modifyDateColumn;
    public TableColumn<SalesBillVoucherViewModel, String> descriptionColumn;

    public SalesOrderTabSkinBillVoucher(SalesOrderWindowController controller) {
        super(controller);
    }

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

    @Override
    protected SalesBillVoucherService getViewModelService() {
        return getSalesBillVoucherService();
    }

    @Override
    public ParamUtils.Builder getSpecification(SalesOrderVo parent) {
        ParamUtils.Builder params = getSpecification();
        params.equals("order", parent.getId());
        return params;
    }

    @Override
    public void initializeTab() {
        super.initializeTab();

        itemTable_idColumn.setCellValueFactory(param -> param.getValue().getId());
        codeColumn.setCellValueFactory(param -> param.getValue().getCode());
        refIdColumn.setCellValueFactory(param -> param.getValue().getRefId().asString());

        employeeColumn.setCellValueFactory(param -> param.getValue().getEmployee());
        employeeColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));

        makerColumn.setCellValueFactory(param -> param.getValue().getMaker());
        makerColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));

        verifierColumn.setCellValueFactory(param -> param.getValue().getVerifier());
        verifierColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));

        makerDateColumn.setCellValueFactory(param -> param.getValue().getMakerDate());
        verifierDateColumn.setCellValueFactory(param -> param.getValue().getVerifierDate());
        modifyDateColumn.setCellValueFactory(param -> param.getValue().getModifyDate());

        descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
    }

    @Override
    protected void createContextMenu(ContextMenu contextMenu) {
        MenuItem item2 = new MenuItem("刷新");
        item2.setOnAction(this::onTableRefreshAction);

        MenuItem item3 = new MenuItem("删除");
        item3.setOnAction(this::onTableDeleteAction);

        contextMenu.getItems().addAll(item2, item3);
    }

    SaleOrdersService getSaleOrdersService() {
        return getCachedBean(SaleOrdersService.class);
    }

    SalesBillVoucherService getSalesBillVoucherService() {
        return getCachedBean(SalesBillVoucherService.class);
    }

    private EmployeeStringConverter getEmployeeStringConverter() {
        return getCachedBean(EmployeeStringConverter.class);
    }

    static class NumberTableCell extends TableCell<SalesBillVoucherViewModel, Double> {
        // "%.1f"
        private final String format;

        public NumberTableCell(String format, String styleClass) {
            this.format = format;
            if (StringUtils.hasText(styleClass)) {
                getStyleClass().add(styleClass);
            }
        }

        @Override
        protected void updateItem(Double item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || item == null) {
                setText(null);
                return;
            }
            setText(String.format(format, item));
        }

        private void setTooltip(ObservableList<ContractItemVo> list, Function<ContractItemVo, Double> getPrice) {
            String text = list.stream().map(v -> {
                ContractVo contract = SpringApp.getBean(ContractService.class).findById(v.getContractId());
                Double price = getPrice.apply(v);
                double quantity = v.getQuantity();
                return contract.getCode() + " " + String.format(format, price) + " x " + quantity + " = "
                        + String.format(format, (price * quantity));
            }).collect(Collectors.joining("\n"));
            setTooltip(text);
        }

        private void setTooltip(String text) {
            Tooltip tooltip = getTooltip();
            if (StringUtils.hasText(text)) {
                if (tooltip == null) {
                    tooltip = new Tooltip();
                    setTooltip(tooltip);
                }
                tooltip.setShowDelay(Duration.ZERO);
                tooltip.setHideDelay(Duration.ZERO);
                tooltip.setText(text);
            } else {
                if (tooltip != null) {
                    tooltip.setText(null);
                }
            }
        }
    }

    static class NumberCellFactory implements
            Callback<TableColumn<SalesBillVoucherViewModel, Double>, TableCell<SalesBillVoucherViewModel, Double>> {
        private final String format;
        private final String styleClass;

        public NumberCellFactory(String format, String styleClass) {
            this.format = format;
            this.styleClass = styleClass;
        }

        @Override
        public TableCell<SalesBillVoucherViewModel, Double> call(TableColumn<SalesBillVoucherViewModel, Double> param) {
            NumberTableCell cell = new NumberTableCell(format, styleClass);
            cell.setAlignment(Pos.CENTER_RIGHT);
            return cell;
        }
    }
}
