package com.ecep.contract.controller.vendor;

import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import com.ecep.contract.util.ProxyUtils;
import org.springframework.util.StringUtils;

import com.ecep.contract.CompanyVendorFileType;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.constant.CompanyVendorConstant;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.model.BaseEnumEntity;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyVendor;
import com.ecep.contract.model.CompanyVendorFile;
import com.ecep.contract.model.CompanyVendorFileTypeLocal;
import com.ecep.contract.service.CompanyVendorFileService;
import com.ecep.contract.task.CompanyVendorEvaluationFormUpdateTask;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyVendorFileViewModel;

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.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import lombok.Setter;

/**
 * 文件 tab
 */
@FxmlPath("/ui/company/vendor/vendor-tab-file.fxml")
public class VendorTabSkinFile
        extends AbstCompanyVendorTableTabSkin<CompanyVendorFile, 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 Button fileTable_reBuildBtn;
    public Button fileTable_updateEvaluationFormBuildBtn;
    public Button fileTable_calcNextSignDateBtn;

    @Setter
    private CompanyVendorFileService companyVendorFileService;

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

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

    @Override
    protected CompanyVendorFileService getViewModelService() {
        return getCompanyVendorFileService();
    }

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

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

        ObservableMap<CompanyVendorFileType, CompanyVendorFileTypeLocal> observableMapByLocal = FXCollections
                .observableMap(companyVendorFileService.getFileTypeLocalMap(getLocale()));
        fileTable_typeColumn.setCellValueFactory(param -> Bindings.valueAt(observableMapByLocal,
                param.getValue().getType()).map(BaseEnumEntity::getValue));

        fileTable_filePathColumn.setCellValueFactory(param -> param.getValue().getFilePath());
        fileTable_filePathColumn.setCellFactory(param -> new FileTableFilePathTableCell());
        fileTable_editFilePathColumn.setCellValueFactory(param -> param.getValue().getEditFilePath());
        fileTable_editFilePathColumn.setCellFactory(param -> new FileTableFilePathTableCell());
        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);

        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) {
        CompanyVendor companyVendor = getParent();
        String path = companyVendor.getPath();
        if (!StringUtils.hasText(path)) {
            setStatus("未设置目录");
            return;
        }
        File dir = new File(path);
        if (!dir.exists()) {
            setStatus("目录错误,不存在");
            return;
        }

        LocalDate nextSignDate = getCompanyVendorFileService().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)) {
                    CompanyVendorFile ccf = new CompanyVendorFile();
                    ccf.setVendor(companyVendor);
                    ccf.setType(CompanyVendorFileType.EvaluationForm);
                    ccf.setFilePath(dest.getAbsolutePath());
                    ccf.setSignDate(nextSignDate);
                    ccf.setValid(true);
                    CompanyVendorFile saved = getCompanyVendorFileService().save(ccf);
                    Platform.runLater(() -> {
                        CompanyVendorFileViewModel model = new CompanyVendorFileViewModel();
                        model.update(saved);
                        dataSet.add(model);
                    });
                    return;
                }
            }
        }

        List<CompanyVendorFile> companyVendorFiles = new ArrayList<>();
        for (File file : files) {
            File dest = new File(dir, file.getName());
            if (file.renameTo(dest)) {
                CompanyVendorFile ccf = new CompanyVendorFile();
                ccf.setVendor(companyVendor);
                ccf.setType(CompanyVendorFileType.General);
                ccf.setFilePath(dest.getAbsolutePath());
                ccf.setValid(false);
                companyVendorFiles.add(ccf);
            }
        }
        getCompanyVendorFileService().saveAll(companyVendorFiles);
        loadTableDataSet();
    }

    public void onFileReBuildingAction(ActionEvent event) {
        CompletableFuture.runAsync(() -> {
            try {
                CompanyVendor companyVendor = getParent();
                if (getCompanyVendorService().reBuildingFiles(companyVendor, (level, msg) -> setStatus(msg))) {
                    loadTableDataSet();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

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

    @Override
    public CompanyVendorFile saveRowData(CompanyVendorFile entity) {
        return getCompanyVendorFileService().save(entity);
    }

    @Override
    public void deleteRowData(CompanyVendorFile entity) {
        getCompanyVendorFileService().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) {
        Company company = viewModel.getCompany().get();
        if (!ProxyUtils.isInitialized(company)) {
            company = getCompanyService().findById(company.getId());
            viewModel.getCompany().set(company);
        }

        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);

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

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

    public void onCalcNextSignDateAction(ActionEvent event) {
        UITools.showDialogAndWait("计算供应商下一个评价日期", "依据已有的供应商评价表和登记采购的合同计算下一个评价日期", ds -> {
            CompanyVendor companyVendor = getCompanyVendorService().findById(viewModel.getId().get());
            LocalDate nextSignDate = getCompanyVendorFileService().getNextSignDate(companyVendor, msg -> {
                Platform.runLater(() -> {
                    ds.add(msg);
                });
            });
            if (nextSignDate != null) {
                Platform.runLater(() -> {
                    ds.add("下一个评价日期：" + nextSignDate);
                });
            }
        });
    }

    class FileTableFilePathTableCell extends TableCell<CompanyVendorFileViewModel, String> {
        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || !StringUtils.hasText(item)) {
                setText("");
                return;
            }

            String path = viewModel.getPath().get();
            if (StringUtils.hasText(path)) {
                if (item.startsWith(path)) {
                    item = "~" + item.substring(path.length());
                }
            }
            setText(item);
        }
    }

    public CompanyVendorFileService getCompanyVendorFileService() {
        if (companyVendorFileService == null) {
            companyVendorFileService = SpringApp.getBean(CompanyVendorFileService.class);
        }
        return companyVendorFileService;
    }

}
