package com.ecep.contract.controller.tab;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.function.Consumer;

import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils;

import com.ecep.contract.CompanyFileType;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.MyProperties;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.controller.company.AbstCompanyTableTabSkin;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.controller.table.cell.CompanyFilePathTableCell;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyFile;
import com.ecep.contract.model.CompanyFileTypeLocal;
import com.ecep.contract.service.CloudTycService;
import com.ecep.contract.service.CompanyFileService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyFileViewModel;

import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;

/**
 *
 */
@FxmlPath("/ui/company/company-tab-file.fxml")
public class CompanyTabSkinFile
        extends AbstCompanyTableTabSkin<CompanyFile, CompanyFileViewModel>
        implements TabSkin, EditableEntityTableTabSkin<CompanyFile, CompanyFileViewModel> {

    public TableColumn<CompanyFileViewModel, Number> idColumn;
    public TableColumn<CompanyFileViewModel, String> typeColumn;
    public TableColumn<CompanyFileViewModel, String> filePathColumn;
    public TableColumn<CompanyFileViewModel, LocalDate> applyDateColumn;
    public TableColumn<CompanyFileViewModel, LocalDate> expiringDateColumn;

    public Button fileTable_file_move_btn;
    public Button fileTable_file_retrieve_from_download_dir_btn;
    public Button fileTable_file_reset_btn;
    public MenuItem fileTable_menu_refresh;
    public MenuItem fileTable_menu_del;
    public MenuItem fileTable_menu_copy_as_matched_by_contract;

    private final ObservableMap<CompanyFileType, CompanyFileTypeLocal> fileTypeLocalMap = FXCollections
            .observableHashMap();

    public CompanyTabSkinFile(CompanyWindowController controller) {
        super(controller);
        setDragAndDrop(true);
        setDragAndDropFileHandler(this::moveFileToCompany);
    }

    protected CompanyFileService getViewModelService() {
        return getCompanyFileService();
    }

    CompanyFileService getCompanyFileService() {
        return getBean(CompanyFileService.class);
    }

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

    @Override
    public void initializeTable() {
        super.initializeTable();
        fileTable_file_move_btn.setOnAction(this::onTableMoveFileAction);
        fileTable_file_retrieve_from_download_dir_btn.setOnAction(this::onTableRetrieveFromDownloadDirAction);
        fileTable_file_reset_btn.setOnAction(this::onTableResetAction);

        idColumn.setCellValueFactory(param -> param.getValue().getId());

        typeColumn.setCellValueFactory(param -> Bindings.valueAt(fileTypeLocalMap, param.getValue().getType())
                .map(CompanyFileTypeLocal::getValue));
        filePathColumn.setCellValueFactory(param -> param.getValue().getFilePath());
        filePathColumn.setCellFactory(param -> new CompanyFilePathTableCell<>(viewModel.getPath()));
        applyDateColumn.setCellValueFactory(param -> param.getValue().getApplyDate());
        expiringDateColumn.setCellValueFactory(param -> param.getValue().getExpiringDate());

        fileTable_menu_refresh.setOnAction(this::onTableRefreshAction);
        fileTable_menu_del.setOnAction(this::onTableDeleteAction);
        fileTable_menu_copy_as_matched_by_contract.setOnAction(this::onTableCopyAsMatchedByContractAction);
        fileTable_menu_copy_as_matched_by_contract.setOnMenuValidation(this::onTableCopyAsMatchedMenuValidation);

        fileTypeLocalMap.putAll(getCompanyFileService().findAllFileTypes(getLocale().toLanguageTag()));
    }

    private void onTableResetAction(ActionEvent event) {
        runAsync(() -> {
            if (getViewModelService().reBuildingFiles(getParent(), (level, msg) -> setStatus(msg))) {
                loadTableDataSet();
            }
        });
    }

    /**
     * 从 下载目录 中查找相关的资质文件
     */
    private void onTableRetrieveFromDownloadDirAction(ActionEvent event) {
        Company company = getParent();
        MyProperties myProperties = getBean(MyProperties.class);
        File dir = myProperties.getDownloadDirectory();
        if (!dir.exists()) {
            setStatus("下载目录 " + dir.getAbsolutePath() + " 不存在，请检查");
            return;
        }

        setStatus("开始检索 下载 文件夹：" + dir.getAbsolutePath() + "...");
        File[] files = dir.listFiles(File::isFile);
        if (files == null) {
            setStatus("检索 下载 文件夹失败");
            return;
        }
        if (files.length == 0) {
            setStatus("下载 文件夹没有文件");
            return;
        }
        setStatus("下载 文件夹中共有文件 " + files.length + " 个文件");

        if (getParentService().retrieveFromDownloadFiles(company, files, (level, msg) -> setStatus(msg))) {
            // fixed if update
            viewModel.update(company);
            loadTableDataSet();
        }
    }

    /**
     * 把文件从 老系统中移到 \\10.84.209.8\项目信息\相关方信息 目录中
     */
    private void onTableMoveFileAction(ActionEvent event) {
        CompanyFileService companyFileService = getCompanyFileService();
        Company company = getParent();
        List<CompanyFile> list = companyFileService.findByCompany(company);
        if (list.isEmpty()) {
            return;
        }
        if (getParentService().makePathAbsent(company)) {
            save(company);
        }

        String path = company.getPath();
        if (!StringUtils.hasText(path)) {
            setStatus("异常, 企业目录未设置");
            return;
        }
        File companyPath = new File(path);
        for (CompanyFile companyFile : list) {
            String filePath = companyFile.getFilePath();
            if (StringUtils.hasText(filePath)) {
                File file = new File(filePath);
                if (file.exists()) {
                    if (file.getParentFile().equals(companyPath)) {
                        continue;
                    }
                    File dest = new File(companyPath, file.getName());
                    if (file.renameTo(dest)) {
                        companyFile.setFilePath(dest.getAbsolutePath());
                        companyFileService.save(companyFile);
                        setStatus(file.getName() + " 移动到 " + companyPath.getName());
                    }
                }
            }
        }
    }

    /**
     *
     */
    private void onTableCopyAsMatchedByContractAction(ActionEvent event) {
        UITools.showDialogAndWait("复制资信评估报告", "按当前评估报告复制一个合同中最匹配的", list -> {
            getViewModelService().copyAsMatchedByContract(getParent(), list);

            onTableCopyAsMatchedAction_(msg -> {
                Platform.runLater(() -> {
                    list.add(msg);
                });
            });
        });
    }

    private void onTableCopyAsMatchedAction_(Consumer<String> state) {
        Company company = getParent();

        CompanyFileViewModel selectedItem = getSelectedItem();
        if (selectedItem == null) {
            state.accept("未选择行");
            return;
        }
        if (selectedItem.getApplyDate().get() == null) {
            state.accept("有效日期不能未空");
            return;
        }

        LocalDate nextCreditReportDate = null;
        try {
            nextCreditReportDate = getViewModelService().getNextCreditReportDate(company, state);
            if (nextCreditReportDate == null) {
                state.accept("没有找到下一个咨询评估日期");
                return;
            }
        } catch (Exception e) {
            state.accept("获取下一个咨询评估日期失败:" + e.getMessage());
            return;
        }

        state.accept("下一个咨询评估日期：" + nextCreditReportDate);

        if (!nextCreditReportDate.isBefore(selectedItem.getApplyDate().get())) {
            state.accept("咨询评估日期晚于下一个咨询评估日期");
            return;
        }

        File src = new File(selectedItem.getFilePath().get());
        if (!src.exists()) {
            state.accept("当前选择行的文件不存在");
            return;
        }

        String srcDate = MyDateTimeUtils.format(selectedItem.getApplyDate().get());
        String destDate = MyDateTimeUtils.format(nextCreditReportDate);
        String srcFileName = src.getName();
        String destFileName;

        // 天眼查的报告
        if (CloudTycService.isTycReport(srcFileName)) {
            state.accept("天眼查的报告按标准格式命名");
            String name = company.getName() + "_" + CloudServiceConstant.TYC_NAME;
            if (srcFileName.contains(CloudServiceConstant.TYC_ENTERPRISE_BASIC_REPORT)) {
                name = name + "_" + CloudServiceConstant.TYC_ENTERPRISE_BASIC_REPORT;
            } else if (srcFileName.contains(CloudServiceConstant.TYC_ENTERPRISE_MAJOR_REPORT)) {
                name = name + "_" + CloudServiceConstant.TYC_ENTERPRISE_MAJOR_REPORT;
            } else if (srcFileName.contains(CloudServiceConstant.TYC_ENTERPRISE_ANALYSIS_REPORT)) {
                name = name + "_" + CloudServiceConstant.TYC_ENTERPRISE_ANALYSIS_REPORT;
            }
            destFileName = name + "_" + destDate + "_cp." + StringUtils.getFilenameExtension(srcFileName);
        } else {
            if (srcFileName.contains(srcDate)) {
                // 如果文件名中包含日期，则替换为新日期
                destFileName = srcFileName.replace(srcDate, destDate + "_cp");
            } else {
                // 如果文件名中不包含日期，则添加日期
                destFileName = company.getName() + "_" + destDate + "_cp."
                        + StringUtils.getFilenameExtension(srcFileName);
            }
        }

        state.accept("新文件名：" + destFileName);

        File dest = new File(src.getParent(), destFileName);
        try {
            FileSystemUtils.copyRecursively(src, dest);
            state.accept("新文件复制成功");
        } catch (IOException e) {
            state.accept("新文件复制失败：" + e.getMessage());
        }

        CompanyFile companyFile = new CompanyFile();
        companyFile.setFilePath(dest.getAbsolutePath());
        companyFile.setApplyDate(nextCreditReportDate);
        companyFile.setExpiringDate(nextCreditReportDate.plusYears(1));
        companyFile.setType(CompanyFileType.CreditReport);
        companyFile.setCompany(company);
        saveRowData(companyFile);

        state.accept("新文件已记录");

        loadTableDataSet();
        state.accept("文件表已刷新");
    }

    /**
     * 当fileTable选中的行是咨询评估时，可用
     *
     * @param event event
     */
    public void onTableCopyAsMatchedMenuValidation(Event event) {
        // 当fileTable选中的行是咨询评估时，可用
        CompanyFileViewModel selectedItem = getSelectedItem();
        if (selectedItem == null) {
            event.consume();
            return;
        }
        CompanyFileType type = selectedItem.getType().get();
        if (type != CompanyFileType.CreditReport) {
            event.consume();
            return;
        }
    }

    @Override
    protected boolean deleteRow(CompanyFileViewModel 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;
    }

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

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