package com.ecep.contract.controller.tab;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import javax.imageio.ImageIO;

import org.apache.pdfbox.Loader;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.io.RandomAccessStreamCache;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.multipdf.Splitter;
import org.apache.pdfbox.pdfwriter.compress.CompressParameters;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.springframework.util.StringUtils;

import com.ecep.contract.ContractFileType;
import com.ecep.contract.ContractPayWay;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.constant.ContractConstant;
import com.ecep.contract.controller.contract.AbstContractTableTabSkin;
import com.ecep.contract.controller.contract.ContractWindowController;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.controller.table.cell.LocalDateFieldTableCell;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ContractFile;
import com.ecep.contract.model.ContractFileTypeLocal;
import com.ecep.contract.model.ContractType;
import com.ecep.contract.service.ContractFileService;
import com.ecep.contract.service.ContractFileTypeService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.ContractFileViewModel;

import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.stage.WindowEvent;
import javafx.util.StringConverter;
import lombok.Setter;

/**
 * 合同文件
 */
@FxmlPath("/ui/contract/contract-tab-file.fxml")
public class ContractTabSkinFiles
        extends AbstContractTableTabSkin<ContractFile, ContractFileViewModel>
        implements TabSkin, EditableEntityTableTabSkin<ContractFile, ContractFileViewModel> {

    public Button fileTableReBuildBtn;
    public MenuItem fileTable_menu_refresh;
    public MenuItem fileTable_menu_del;
    public Menu fileTable_menu_pdf;
    public Menu fileTable_menu_update;
    public Menu fileTable_menu_change_type;
    public Menu fileTable_menu_change_type_and_name;
    public TableColumn<ContractFileViewModel, Number> fileTable_idColumn;
    public TableColumn<ContractFileViewModel, ContractFileTypeLocal> fileTable_typeColumn;
    public TableColumn<ContractFileViewModel, String> fileTable_filePathColumn;
    public TableColumn<ContractFileViewModel, LocalDate> fileTable_applyDateColumn;
    public TableColumn<ContractFileViewModel, String> fileTable_descriptionColumn;

    @Setter
    private ContractFileService contractFileService;
    private final ObservableMap<ContractFileType, ContractFileTypeLocal> fileTypeLocalMap = FXCollections
            .observableHashMap();

    public ContractTabSkinFiles(ContractWindowController controller) {
        super(controller);
        setDragAndDrop(true);
        setDragAndDropFileHandler(this::moveFileToCustomer);
    }

    @Override
    protected ContractFileService getViewModelService() {
        return getContractFileService();
    }

    public ContractFileService getContractFileService() {
        if (contractFileService == null) {
            contractFileService = SpringApp.getBean(ContractFileService.class);
        }
        return contractFileService;
    }

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

    static class ContractFileTypeLocalStringConverter extends StringConverter<ContractFileTypeLocal> {
        @Override
        public String toString(ContractFileTypeLocal local) {
            if (local == null) {
                return "-";
            }
            return local.getValue();
        }

        @Override
        public ContractFileTypeLocal fromString(String string) {
            return null;
        }
    }

    @Override
    public void initializeTab() {
        TableView<ContractFileViewModel> table = getTableView();
        ContractPayWay payWay = viewModel.getPayWay().get();
        ContractType contractType = viewModel.getType().get();
        boolean isCustomer = payWay == ContractPayWay.RECEIVE;
        boolean isVendor = payWay == ContractPayWay.PAY;

        fileTable_menu_refresh.setOnAction(this::onTableRefreshAction);

        table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        table.getContextMenu().setOnShowing(this::onFileTableContextMenuShowing);

        fileTableReBuildBtn.setOnAction(this::onFileReBuildingAction);

        fileTable_idColumn.setCellValueFactory(param -> param.getValue().getId());
        fileTable_idColumn.setEditable(false);
        fileTable_idColumn.setReorderable(false);

        fileTable_typeColumn
                .setCellValueFactory(param -> Bindings.valueAt(fileTypeLocalMap, param.getValue().getType()));
        fileTable_typeColumn
                .setCellFactory(param -> new TextFieldTableCell<>(new ContractFileTypeLocalStringConverter()));
        // 监听 type map 变化
        fileTypeLocalMap
                .addListener((MapChangeListener<? super ContractFileType, ? super ContractFileTypeLocal>) change -> {
                    List<ContractFileTypeLocal> types = fileTypeLocalMap.values().stream().filter(typeLocal -> {
                        ContractFileType type = typeLocal.getType();
                        if (type == null) {
                            return false;
                        }
                        if (isCustomer && !type.isSupportCustomer()) {
                            return false;
                        }
                        return !isVendor || type.isSupportVendor();
                    }).toList();

                    fileTable_menu_change_type.getItems().setAll(types.stream()
                            .map(typeLocal -> {
                                MenuItem item = new MenuItem();
                                item.setText(typeLocal.getValue());
                                item.getProperties().put("typeLocal", typeLocal);
                                item.setOnAction(this::onFileTableContextMenuChangeTypeAndNameAction);
                                return item;
                            }).toList());

                    fileTable_menu_change_type_and_name.getItems().setAll(types.stream()
                            .filter(typeLocal -> StringUtils.hasText(typeLocal.getSuggestFileName()))
                            .map(typeLocal -> {
                                MenuItem item = new MenuItem();
                                item.setText(typeLocal.getValue());
                                item.getProperties().put("typeLocal", typeLocal);
                                item.getProperties().put("rename", true);
                                item.setOnAction(this::onFileTableContextMenuChangeTypeAndNameAction);
                                return item;
                            }).toList());
                });

        fileTable_typeColumn.setEditable(false);

        /* 文件名编辑器 */
        fileTable_filePathColumn.setCellValueFactory(param -> param.getValue().getFileName());
        fileTable_filePathColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        fileTable_filePathColumn.setEditable(true);
        fileTable_filePathColumn.setOnEditCommit(this::onFilePathColumnEditCommitAction);

        /* 日期编辑器 */
        fileTable_applyDateColumn.setCellValueFactory(param -> param.getValue().getApplyDate());
        fileTable_applyDateColumn.setCellFactory(LocalDateFieldTableCell.forTableColumn());
        fileTable_applyDateColumn.setEditable(true);
        fileTable_applyDateColumn.setOnEditCommit(this::onFileTableApplyDateColumnEditCommitAction);

        /* 备注编辑器 */
        fileTable_descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
        fileTable_descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        fileTable_descriptionColumn.setEditable(true);
        fileTable_descriptionColumn.setOnEditCommit(this::onFileTableDescriptionColumnEditCommitAction);

        table.setEditable(true);

        fileTable_menu_del.setOnAction(this::onTableDeleteAction);

        MenuItem composePdfMenu = createComposePdfMenu();
        MenuItem splitPDFMenu = createSplitPDFMenu();
        fileTable_menu_pdf.getItems().setAll(splitPDFMenu, composePdfMenu);
        fileTable_menu_pdf.setOnMenuValidation(e -> {
            splitPDFMenu.setDisable(true);
            composePdfMenu.setVisible(false);
            SelectionMode selectionMode = table.getSelectionModel().getSelectionMode();
            // 是否多选
            if (table.getSelectionModel().getSelectedItems().size() > 1) {
                // 多选时启用合并菜单
                if (selectionMode == SelectionMode.MULTIPLE) {
                    composePdfMenu.setVisible(true);
                }
            } else {
                ContractFileViewModel selectedItem = table.getSelectionModel().getSelectedItem();
                if (selectedItem != null) {
                    String extension = StringUtils.getFilenameExtension(selectedItem.getFileName().get());
                    splitPDFMenu.setDisable(extension == null || !extension.equals("pdf"));
                }
            }
        });
        // 当 菜单 onShowing 时触发
        fileTable_menu_change_type.setOnMenuValidation(e -> {
            System.out.println("fileTable_menu_change_type:setOnMenuValidation");
        });
        // 当 菜单 onShowing 时触发
        fileTable_menu_change_type_and_name.setOnMenuValidation(e -> {
            System.out.println("fileTable_menu_change_type_and_name:setOnMenuValidation");
        });

        fileTable_menu_update.getItems().setAll(
                createCustomerContractCostByTemplateUpdateMenuItem(),
                createCustomerContractBidByTemplateUpdateMenuItem(),
                createCustomerContractApplyByTemplateUpdateMenuItem(),
                createVendorContractRequestByTemplateUpdateMenuItem(),
                createVendorContractApplyByTemplateUpdateMenuItem());

        fileTypeLocalMap.putAll(getCachedBean(ContractFileTypeService.class).findAll(getLocale()));
        super.initializeTab();
    }

    private MenuItem createSplitPDFMenu() {
        MenuItem item = new MenuItem();
        item.setText("拆分PDF");
        item.setOnAction(this::onFileTableSplitPDFAction);
        return item;
    }

    private MenuItem createComposePdfMenu() {
        MenuItem item = new MenuItem();
        item.setText("合并PDF");
        item.setOnAction(this::onFileTableComposePDFAction_V2);
        return item;
    }

    /**
     * 合并PDF
     *
     * @param event 菜单事件
     */
    private void onFileTableComposePDFAction(ActionEvent event) {
        Contract contract = getParent();
        if (!StringUtils.hasText(contract.getPath())) {
            setStatus("合同未设置路径");
            return;
        }
        File contractPath = new File(contract.getPath());
        if (!contractPath.exists()) {
            setStatus("合同路径不存在，请检查");
            return;
        }

        ObservableList<ContractFileViewModel> selectedItems = getTableView().getSelectionModel().getSelectedItems();
        if (selectedItems.isEmpty()) {
            setStatus("请选择文件");
            return;
        }
        List<ContractFileViewModel> rows = selectedItems.stream().filter(selectedItem -> {
            String fileName = selectedItem.getFileName().get();
            if (!StringUtils.hasText(fileName)) {
                return false;
            }
            File file = new File(contractPath, fileName);
            return file.exists();
        }).toList();

        if (rows.isEmpty()) {
            setStatus("请选择PDF文件");
            return;
        }

        PDFMergerUtility merger = new PDFMergerUtility();
        File dest = new File(contractPath, "合并的" + rows.getFirst().getFileName().get());
        merger.setDestinationFileName(dest.getAbsolutePath());
        for (ContractFileViewModel row : rows) {
            try {
                File file = new File(contractPath, row.getFileName().get());
                String extension = StringUtils.getFilenameExtension(file.getName());
                if (!"pdf".equalsIgnoreCase(extension)) {
                    merger.addSource(file);
                } else {
                    if (!"jpg".equalsIgnoreCase(extension)) {
                        PDDocument document = new PDDocument();
                    }
                }

            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            merger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly().streamCache); // null
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        ContractFileViewModel append = new ContractFileViewModel();
        append.getContract().set(contract);
        append.getFileName().set(dest.getName());
        append.getType().set(ContractFileType.General);
        saveRow(append);
        getTableView().getItems().add(append);

        for (ContractFileViewModel row : rows) {
            if (deleteRow(row, false)) {
                getTableView().getItems().remove(row);
            }
        }
    }

    private void onFileTableComposePDFAction_V2(ActionEvent event) {
        Contract contract = getParent();
        if (!StringUtils.hasText(contract.getPath())) {
            setStatus("合同未设置路径");
            return;
        }
        File contractPath = new File(contract.getPath());
        if (!contractPath.exists()) {
            setStatus("合同路径不存在，请检查");
            return;
        }

        ObservableList<ContractFileViewModel> selectedItems = getTableView().getSelectionModel().getSelectedItems();
        if (selectedItems.isEmpty()) {
            setStatus("请选择文件");
            return;
        }
        List<ContractFileViewModel> rows = selectedItems.stream().filter(selectedItem -> {
            String fileName = selectedItem.getFileName().get();
            if (!StringUtils.hasText(fileName)) {
                return false;
            }
            File file = new File(contractPath, fileName);
            return file.exists();
        }).toList();

        if (rows.isEmpty()) {
            setStatus("请选择PDF文件");
            return;
        }

        List<File> files = rows.stream().map(v -> new File(contractPath, v.getFileName().get())).toList();
        PDFMergerUtility merger = new PDFMergerUtility();
        File dest = new File(contractPath, "合并的" + stripFilename(files.getFirst()) + ".pdf");
        String[] imageReaderFormats = null;
        List<PDDocument> tobeClosed = new ArrayList<>();
        RandomAccessStreamCache.StreamCacheCreateFunction createFunction = IOUtils.createMemoryOnlyStreamCache();
        try (PDDocument destination = new PDDocument(createFunction)) {
            for (File file : files) {
                String extension = StringUtils.getFilenameExtension(file.getName());
                if ("pdf".equalsIgnoreCase(extension)) {
                    PDDocument doc = Loader.loadPDF(file);
                    tobeClosed.add(doc);
                    merger.appendDocument(destination, doc);
                } else {
                    if (imageReaderFormats == null) {
                        imageReaderFormats = ImageIO.getReaderFormatNames();
                    }
                    boolean found = false;
                    for (String format : imageReaderFormats) {
                        if (format.equals(extension)) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        continue;
                    }

                    PDPage page = new PDPage();
                    // 加载 PNG 图片
                    BufferedImage image = ImageIO.read(file);
                    // 将图片添加到 PDF
                    try (PDPageContentStream contentStream = new PDPageContentStream(destination, page)) {
                        PDImageXObject pdImage = LosslessFactory.createFromImage(destination, image);
                        float scale = 1f; // 图片缩放比例
                        contentStream.drawImage(pdImage, 0, 0,
                                pdImage.getWidth() * scale,
                                pdImage.getHeight() * scale);
                    }
                    destination.addPage(page);
                }

            }
            destination.save(dest, CompressParameters.DEFAULT_COMPRESSION);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            for (PDDocument doc : tobeClosed) {
                IOUtils.closeQuietly(doc);
            }
        }

        ContractFileViewModel append = new ContractFileViewModel();
        append.getContract().set(contract);
        append.getFileName().set(dest.getName());
        append.getType().set(ContractFileType.General);
        saveRow(append);
        getTableView().getItems().add(append);

        for (ContractFileViewModel row : rows) {
            if (deleteRow(row, false)) {
                getTableView().getItems().remove(row);
            }
        }
    }

    private String stripFilename(File file) {
        String filename = file.getName();
        String extension = StringUtils.getFilenameExtension(filename);
        if (extension == null) {
            return filename;
        }
        return filename.substring(0, filename.length() - (extension.length() + 1));
    }

    private MenuItem createVendorContractRequestByTemplateUpdateMenuItem() {
        MenuItem item = new MenuItem();
        item.setText("采购与服务申请表");
        item.visibleProperty().bind(viewModel.getPayWay().isEqualTo(ContractPayWay.PAY));
        return item;
    }

    private MenuItem createVendorContractApplyByTemplateUpdateMenuItem() {
        MenuItem item = new MenuItem();
        item.setText("采购合同审批表");
        item.visibleProperty().bind(viewModel.getPayWay().isEqualTo(ContractPayWay.PAY));
        return item;
    }

    private MenuItem createCustomerContractApplyByTemplateUpdateMenuItem() {
        MenuItem item = new MenuItem();
        item.setText("销售合同审批表");
        item.visibleProperty().bind(viewModel.getPayWay().isEqualTo(ContractPayWay.RECEIVE));
        return item;
    }

    private MenuItem createCustomerContractBidByTemplateUpdateMenuItem() {
        MenuItem item = new MenuItem();
        item.setText("投标报价审批表");

        item.visibleProperty().bind(viewModel.getPayWay().isEqualTo(ContractPayWay.RECEIVE));
        return item;
    }

    private MenuItem createCustomerContractCostByTemplateUpdateMenuItem() {
        MenuItem item = new MenuItem();
        item.setText("成本核算审批表");
        item.visibleProperty().bind(viewModel.getPayWay().isEqualTo(ContractPayWay.RECEIVE));
        item.setOnAction(event -> {
            Contract contract = getContractService().findById(viewModel.getId().get());
            if (contract == null) {
                setStatus("异常，对应的合同不存在#" + viewModel.getId().get());
                return;
            }
            if (!StringUtils.hasText(contract.getPath())) {
                setStatus("合同目录未创建");
                return;
            }

            String template = controller.getConfService().getString(ContractConstant.KEY_CUSTOMER_COST_TEMPLATE);
            if (!StringUtils.hasText(template)) {
                setStatus("模板文件未配置");
                return;
            }

            ContractFileViewModel model = dataSet.stream()
                    .filter(v -> v.getType().get().equals(ContractFileType.Cost))
                    .findFirst().orElse(null);
            if (model == null) {
                ContractFile file = new ContractFile();
                file.setContract(contract);
                file.setType(ContractFileType.Cost);
                file.setApplyDate(LocalDate.now());

                String fileName = item.getText();
                ContractFileTypeLocal local = fileTypeLocalMap.get(ContractFileType.CostForm);
                if (local != null) {
                    if (StringUtils.hasText(local.getSuggestFileName())) {
                        fileName = local.getSuggestFileName();
                    }
                }
                String dest = contract.getCode() + "-" + fileName + "." + StringUtils.getFilenameExtension(template);
                file.setFileName(dest);

                file = getContractFileService().save(file);

                model = new ContractFileViewModel();
                model.update(file);

                dataSet.add(model);
            }

            CustomerContractCostFormUpdateTask task = new CustomerContractCostFormUpdateTask();
            task.setContract(contract);
            task.setTemplate(template);
            task.setFileName(model.getFileName().get());
            task.setApplyDate(model.getApplyDate().get());

            UITools.showTaskDialogAndWait("更新 " + model.getFileName().get(), task, null);

        });
        return item;
    }

    private void onFileTableDescriptionColumnEditCommitAction(
            TableColumn.CellEditEvent<ContractFileViewModel, String> event) {
        acceptCellEditEvent(event, ContractFileViewModel::getDescription);
    }

    private void onFileTableApplyDateColumnEditCommitAction(
            TableColumn.CellEditEvent<ContractFileViewModel, LocalDate> event) {
        acceptCellEditEvent(event, ContractFileViewModel::getApplyDate);
    }

    private void onFilePathColumnEditCommitAction(TableColumn.CellEditEvent<ContractFileViewModel, String> event) {
        ContractFileViewModel row = event.getRowValue();
        File src = new File(viewModel.getPath().get(), row.getFileName().get());
        File desc = new File(viewModel.getPath().get(), event.getNewValue());
        if (!src.exists()) {
            setStatus("原文件不存在, " + src.getAbsolutePath());
            return;
        }
        if (desc.exists()) {
            setStatus("目标文件已存在, " + desc.getAbsolutePath());
            return;
        }
        if (src.renameTo(desc)) {
            acceptCellEditEvent(event, ContractFileViewModel::getFileName);
        }
    }

    @Override
    protected void onTableRowDoubleClickedAction(ContractFileViewModel item) {
        String parent = viewModel.getPath().get();
        if (!getContractService().existsContractPath(getEntity())) {
            setStatus("合同的目录未设置或者无效，请检查!");
            return;
        }

        File file = new File(parent, item.getFileName().get());
        if (!file.exists()) {
            setStatus("文件不存在 " + file.getName());
            return;
        }
        DesktopUtils.showInExplorer(file);
    }

    public void onFileTableContextMenuShowing(WindowEvent windowEvent) {
        ContextMenu contextMenu = (ContextMenu) windowEvent.getSource();
        ContractFileViewModel selectedItem = getSelectedItem();
        if (selectedItem == null) {
            // 未选择行
            windowEvent.consume();
            // contextMenu.hide();
            fileTable_menu_del.setVisible(false);
            fileTable_menu_change_type.setVisible(false);
            fileTable_menu_change_type_and_name.setVisible(false);
            return;
        }
        fileTable_menu_del.setVisible(true);

        //
        fileTable_menu_change_type.setVisible(true);
        for (MenuItem item : fileTable_menu_change_type.getItems()) {
            ContractFileTypeLocal typeLocal = (ContractFileTypeLocal) item.getProperties().get("typeLocal");
            item.setVisible(typeLocal.getType() != selectedItem.getType().get());
        }

        fileTable_menu_change_type_and_name.setVisible(true);
        for (MenuItem item : fileTable_menu_change_type.getItems()) {
            ContractFileTypeLocal typeLocal = (ContractFileTypeLocal) item.getProperties().get("typeLocal");
            item.setVisible(typeLocal.getType() != selectedItem.getType().get());
        }

    }

    private void onFileTableContextMenuChangeTypeAndNameAction(ActionEvent event) {
        MenuItem item = (MenuItem) event.getSource();

        ObservableList<ContractFileViewModel> selectedItems = getTableView().getSelectionModel().getSelectedItems();
        if (selectedItems == null || selectedItems.isEmpty()) {
            return;
        }
        ContractFileTypeLocal typeLocal = (ContractFileTypeLocal) item.getProperties().get("typeLocal");
        if (typeLocal == null) {
            return;
        }

        for (ContractFileViewModel selectedItem : selectedItems) {
            if (typeLocal.getType() == selectedItem.getType().get()) {
                continue;
            }

            Boolean rename = (Boolean) item.getProperties().get("rename");
            String suggestFileName = typeLocal.getSuggestFileName();
            if (rename != null && rename && StringUtils.hasText(suggestFileName)) {
                String fileName = selectedItem.getFileName().get();
                String extension = StringUtils.getFilenameExtension(fileName);
                LocalDate localDate = selectedItem.getApplyDate().get();
                String contractCode = viewModel.getCode().get();
                String newFileName = contractCode + "-" + suggestFileName
                        + (localDate == null ? "" : ("-" + MyDateTimeUtils.format(localDate))) + "." + extension;

                // 新旧文件名不一样，需要改名
                if (!Objects.equals(newFileName, fileName)) {
                    File src = new File(viewModel.getPath().get(), fileName);
                    File desc = new File(viewModel.getPath().get(), newFileName);
                    if (src.renameTo(desc)) {
                        selectedItem.getType().set(typeLocal.getType());
                        selectedItem.getFileName().set(newFileName);
                        saveRow(selectedItem);
                    }
                } else {
                    setStatus("文件名没有变化");
                }
            }

            selectedItem.getType().set(typeLocal.getType());
            saveRow(selectedItem);
            setStatus("文件类型修改成功");
        }
    }

    @Override
    public ContractFile loadRowData(ContractFileViewModel row) {
        return getContractFileService().findById(row.getId().get());
    }

    @Override
    public ContractFile saveRowData(ContractFile entity) {
        return getContractFileService().save(entity);
    }

    @Override
    public void deleteRowData(ContractFile entity) {
        getContractFileService().delete(entity);
    }

    /**
     * 重置文件
     * <br>
     * 依据已存在的文件重建
     */
    public void onFileReBuildingAction(ActionEvent event) {
        Contract contract = getParent();
        ContractFilesRebuildTasker task = new ContractFilesRebuildTasker();
        task.setContract(contract);
        UITools.showTaskDialogAndWait("文件重置", task, null);

        if (task.isRepaired()) {
            loadTableDataSet();
        }
    }

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

        for (File file : files) {
            File dest = new File(dir, file.getName());
            if (file.renameTo(dest)) {
                ContractFile ccf = new ContractFile();
                ccf.setContract(contract);
                ccf.setType(ContractFileType.General);
                ccf.setFileName(dest.getName());
                getContractFileService().save(ccf);
            }
        }

        loadTableDataSet();
    }

    public void onFileTableSplitPDFAction(ActionEvent event) {
        ContractFileViewModel selectedItem = getSelectedItem();
        if (selectedItem == null) {
            // 未选择行
            return;
        }

        Contract contract = getParent();
        if (!StringUtils.hasText(contract.getPath())) {
            setStatus("合同未设置路径");
            return;
        }
        File contractPath = new File(contract.getPath());
        if (!contractPath.exists()) {
            setStatus("合同路径不存在，请检查");
            return;
        }

        String fileName = selectedItem.getFileName().get();
        if (!StringUtils.hasText(fileName)) {
            setStatus("选中行没有文件信息");
            return;
        }
        if (!"pdf".equalsIgnoreCase(StringUtils.getFilenameExtension(fileName))) {
            setStatus(fileName + "不是PDF文件，支持拆分");
            return;
        }

        File pdfFile = new File(contractPath, fileName);
        if (!pdfFile.exists()) {
            setStatus(fileName + "不存在，请检查");
            return;
        }

        try (PDDocument pdDocument = Loader.loadPDF(pdfFile)) {
            Splitter splitter = new Splitter();
            List<PDDocument> pages = splitter.split(pdDocument);
            String name = StringUtils.stripFilenameExtension(fileName);
            for (int i = 0; i < pages.size(); i++) {
                PDDocument page = pages.get(i);
                File outputFile = new File(contractPath, name + "-" + (i + 1) + ".pdf");
                page.save(outputFile);
                page.close();
                ContractFile contractFile = new ContractFile();
                contractFile.setContract(contract);
                getContractService().syncContractFile(contractFile, outputFile, (lv, message) -> {
                    setStatus(message);
                });
                ContractFile saved = getContractFileService().save(contractFile);
                dataSet.add(ContractFileViewModel.from(saved));
            }
        } catch (Exception e) {
            setStatus(e.getMessage());
            return;
        }

        // loadFileTableDataSet(contract);
    }

    @Override
    protected void onTableDeleteAction(ActionEvent event) {
        Contract contract = getParent();
        String path = contract.getPath();
        if (!StringUtils.hasText(path)) {
            setStatus("未设置目录");
            return;
        }
        super.onTableDeleteAction(event);
    }

    @Override
    public boolean deleteRow(ContractFileViewModel row) {
        return deleteRow(row, true);
    }

    protected boolean deleteRow(ContractFileViewModel row, boolean confirm) {
        boolean deleted = super.deleteRow(row);
        if (deleted) {
            Contract contract = getParent();
            File file = new File(contract.getPath(), row.getFileName().get());
            if (!file.exists()) {
                setStatus(file.getAbsolutePath() + " 文件不存在, 无法删除");
            } else {
                if (confirm) {
                    UITools.showConfirmation("数据记录已经删除，请确认是否删除物理文件", file.getAbsolutePath())
                            .thenAccept(buttonType -> {
                                if (buttonType == ButtonType.OK) {
                                    if (file.delete()) {
                                        setStatus("删除文件 " + file.getAbsolutePath());
                                    }
                                }
                            });
                } else {
                    if (file.delete()) {
                        setStatus("删除文件 " + file.getAbsolutePath());
                    }
                }
            }
        }
        return deleted;
    }
}
