package com.ecep.contract.controller.vendor;

import java.io.File;
import java.time.LocalDate;
import java.util.List;

import javafx.scene.control.*;
import org.springframework.util.StringUtils;

import com.ecep.contract.DesktopUtils;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.constant.CompanyVendorConstant;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.cell.FilePathTableCell;
import com.ecep.contract.service.VendorFileService;
import com.ecep.contract.service.VendorFileTypeService;
import com.ecep.contract.task.CompanyVendorEvaluationFormUpdateTask;
import com.ecep.contract.task.VendorReBuildFilesTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyVendorFileViewModel;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.VendorFileTypeLocalVo;
import com.ecep.contract.vo.VendorFileVo;
import com.ecep.contract.vo.VendorVo;

import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import javafx.event.ActionEvent;
import javafx.scene.control.cell.CheckBoxTableCell;
import lombok.Setter;

/**
 * 文件 tab
 */
@FxmlPath("/ui/company/vendor/vendor-tab-file.fxml")
public class VendorTabSkinFile
        extends AbstVendorTableTabSkin<VendorFileVo, CompanyVendorFileViewModel>
        implements TabSkin {

    public TableColumn<CompanyVendorFileViewModel, Number> fileTable_idColumn;
    public TableColumn<CompanyVendorFileViewModel, String> fileTable_typeColumn;
    public TableColumn<CompanyVendorFileViewModel, String> fileTable_filePathColumn;
    public TableColumn<CompanyVendorFileViewModel, String> fileTable_editFilePathColumn;
    public TableColumn<CompanyVendorFileViewModel, LocalDate> fileTable_signDateColumn;
    public TableColumn<CompanyVendorFileViewModel, Boolean> fileTable_validColumn;
    public TableColumn<CompanyVendorFileViewModel, String> fileTable_descriptionColumn;

    public MenuItem fileTable_menu_refresh;
    public MenuItem fileTable_menu_del;
    public MenuItem fileTable_menu_move_to_company_path;
    public Menu fileTable_menu_set_valid;
    public MenuItem fileTable_menu_set_valid_true;
    public MenuItem fileTable_menu_set_valid_false;

    public Button fileTable_reBuildBtn;
    public Button fileTable_updateEvaluationFormBuildBtn;
    public Button fileTable_calcNextSignDateBtn;

    @Setter
    private VendorFileService vendorFileService;

    public VendorTabSkinFile(VendorWindowController controller) {
        super(controller);
        setDragAndDrop(true);
        setDragAndDropFileHandler(this::moveFileToCustomer);
    }

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

    @Override
    protected VendorFileService getViewModelService() {
        return getVendorFileService();
    }

    @Override
    public void initializeTab() {
        TableView<CompanyVendorFileViewModel> table = getTableView();

        table.disableProperty().bind(viewModel.getPath().isEmpty());
        fileTable_idColumn.setCellValueFactory(param -> param.getValue().getId());

        ObservableMap<VendorFileType, VendorFileTypeLocalVo> observableMapByLocal = FXCollections
                .observableMap(getCachedBean(VendorFileTypeService.class).findAll(getLocale()));

        fileTable_typeColumn.setCellValueFactory(param -> Bindings.valueAt(observableMapByLocal,
                param.getValue().getType()).map(VendorFileTypeLocalVo::getValue));

        fileTable_filePathColumn.setCellValueFactory(param -> param.getValue().getFilePath());
        fileTable_filePathColumn.setCellFactory(FilePathTableCell.forTableColumn(viewModel.getPath()));

        fileTable_editFilePathColumn.setCellValueFactory(param -> param.getValue().getEditFilePath());
        fileTable_editFilePathColumn.setCellFactory(FilePathTableCell.forTableColumn(viewModel.getPath()));

        fileTable_signDateColumn.setCellValueFactory(param -> param.getValue().getSignDate());

        fileTable_validColumn.setEditable(true);
        fileTable_validColumn.setCellValueFactory(param -> param.getValue().getValid());
        fileTable_validColumn.setCellFactory(param -> new CheckBoxTableCell<>());

        fileTable_reBuildBtn.setOnAction(this::onFileReBuildingAction);
        fileTable_updateEvaluationFormBuildBtn.setOnAction(this::onUpdateEvaluationFormAction);
        fileTable_calcNextSignDateBtn.setOnAction(this::onCalcNextSignDateAction);

        fileTable_menu_refresh.setOnAction(this::onTableRefreshAction);
        fileTable_menu_del.setOnAction(this::onTableDeleteAction);
        fileTable_menu_move_to_company_path.setOnAction(this::onFileTableMoveToCompanyPathAction);

        // 设置有效性菜单项事件处理
        fileTable_menu_set_valid_true.setOnAction(e -> setValidValue(true));
        fileTable_menu_set_valid_false.setOnAction(e -> setValidValue(false));

        // 当表格中没有选中项时，菜单项不显示
        fileTable_menu_set_valid.visibleProperty()
                .bind(Bindings.isNotEmpty(table.getSelectionModel().getSelectedItems()));

        super.initializeTab();
    }

    @Override
    protected void onTableRowDoubleClickedAction(CompanyVendorFileViewModel item) {
        File file = new File(item.getFilePath().get());
        if (!file.exists()) {
            setStatus("文件不存在 " + file.getName());
            return;
        }
        DesktopUtils.showInExplorer(file);
    }

    private void moveFileToCustomer(List<File> files) {
        VendorVo companyVendor = getParent();
        String path = companyVendor.getPath();
        if (!StringUtils.hasText(path)) {
            setStatus("未设置目录");
            return;
        }
        File dir = new File(path);
        if (!dir.exists()) {
            setStatus("目录错误,不存在");
            return;
        }

        LocalDate nextSignDate = getVendorFileService().getNextSignDate(companyVendor, this::setStatus);
        if (nextSignDate != null && files.size() == 1) {
            File file = files.getFirst();
            String fileName = file.getName();
            if (fileName.startsWith("S")) {
                String destFileName = CompanyVendorConstant.EVALUATION_FORM_NAME1 + "_"
                        + MyDateTimeUtils.format(nextSignDate)
                        + "." + StringUtils.getFilenameExtension(fileName);
                File dest = new File(dir, destFileName);
                if (file.renameTo(dest)) {
                    VendorFileVo ccf = new VendorFileVo();
                    ccf.setVendorId(companyVendor.getId());
                    ccf.setType(VendorFileType.EvaluationForm);
                    ccf.setFilePath(dest.getAbsolutePath());
                    ccf.setSignDate(nextSignDate);
                    ccf.setValid(true);
                    VendorFileVo saved = getVendorFileService().save(ccf);
                    Platform.runLater(() -> {
                        CompanyVendorFileViewModel model = new CompanyVendorFileViewModel();
                        model.update(saved);
                        dataSet.add(model);
                    });
                    return;
                }
            }
        }

        for (File file : files) {
            File dest = new File(dir, file.getName());
            if (file.renameTo(dest)) {
                VendorFileVo ccf = new VendorFileVo();
                ccf.setVendorId(companyVendor.getId());
                ccf.setType(VendorFileType.General);
                ccf.setFilePath(dest.getAbsolutePath());
                ccf.setValid(false);
                getVendorFileService().save(ccf);
            }
        }
        loadTableDataSet();
    }

    public void onFileReBuildingAction(ActionEvent event) {
        VendorReBuildFilesTasker tasker = new VendorReBuildFilesTasker();
        tasker.setVendor(getEntity());
        UITools.showTaskDialogAndWait("重建文件", tasker, null);
        if (tasker.isModified()) {
            loadTableDataSet();
        }
    }

    @Override
    public VendorFileVo loadRowData(CompanyVendorFileViewModel row) {
        return getVendorFileService().findById(row.getId().get());
    }

    @Override
    public VendorFileVo saveRowData(VendorFileVo entity) {
        return getVendorFileService().save(entity);
    }

    @Override
    public void deleteRowData(VendorFileVo entity) {
        getVendorFileService().delete(entity);
    }

    @Override
    protected boolean deleteRow(CompanyVendorFileViewModel row) {
        String path = row.getFilePath().get();
        if (super.deleteRow(row)) {
            File file = new File(path);
            if (file.exists()) {
                UITools.showConfirmation("数据记录已经删除，请确认是否删除物理文件", path)
                        .thenAccept(buttonType -> {
                            if (buttonType == ButtonType.OK) {
                                if (file.delete()) {
                                    setStatus("删除文件 " + path);
                                }
                            }
                        });
            }
            return true;
        }
        return false;
    }

    public void onFileTableMoveToCompanyPathAction(ActionEvent event) {
        Integer companyId = viewModel.getCompany().get();
        CompanyVo company = getCompanyService().findById(companyId);

        if (!StringUtils.hasText(company.getPath())) {
            setStatus("公司目录未设置");
            return;
        }

        File companyPath = new File(company.getPath());
        if (!companyPath.exists()) {
            setStatus("公司目录设置设置异常，无法访问");
            return;
        }

        CompanyVendorFileViewModel selectedItem = getSelectedItem();
        if (selectedItem == null) {
            return;
        }
        String filePath = selectedItem.getFilePath().get();
        String editFilePath = selectedItem.getEditFilePath().get();

        if (StringUtils.hasText(filePath)) {
            File file = new File(filePath);
            if (file.exists()) {
                File dest = new File(companyPath, file.getName());
                if (file.renameTo(dest)) {
                    setStatus(file.getAbsolutePath() + " -> " + dest.getAbsolutePath());
                }
            }
        }

        if (StringUtils.hasText(editFilePath)) {
            File file = new File(editFilePath);
            if (file.exists()) {
                File dest = new File(companyPath, file.getName());
                if (file.renameTo(dest)) {
                    setStatus(file.getAbsolutePath() + " -> " + dest.getAbsolutePath());
                }
            }
        }

        deleteRow(selectedItem);

        // getVendorService().deleteFileById(selectedItem.getId().get());
        // dataSet.remove(selectedItem);
    }

    public void onUpdateEvaluationFormAction(ActionEvent event) {
        CompanyVendorEvaluationFormUpdateTask task = new CompanyVendorEvaluationFormUpdateTask();
        task.setVendor(getEntity());
        UITools.showTaskDialogAndWait("更新评价表", task, null);
        loadTableDataSet();
    }

    public void onCalcNextSignDateAction(ActionEvent event) {
        VendorNextSignDateTask task = new VendorNextSignDateTask();
        task.setVendor(getEntity());
        UITools.showTaskDialogAndWait("计算供应商的下一个评价日期", task, null);
    }

    public VendorFileService getVendorFileService() {
        if (vendorFileService == null) {
            vendorFileService = SpringApp.getBean(VendorFileService.class);
        }
        return vendorFileService;
    }

    /**
     * 设置选中行的valid值
     * 
     * @param valid 有效性值
     */
    private void setValidValue(boolean valid) {
        List<CompanyVendorFileViewModel> selectedItems = getTableView().getSelectionModel().getSelectedItems();
        if (selectedItems.isEmpty()) {
            return;
        }

        for (CompanyVendorFileViewModel item : selectedItems) {
            // 更新视图模型的值
            item.getValid().set(valid);

            // 保存到后端
            VendorFileVo entity = loadRowData(item);
            entity.setValid(valid);
            saveRowData(entity);
        }

        setStatus("已更新" + selectedItems.size() + "条记录的有效性状态");
    }

}
