package top.r3944realms.docchecktoolrefactored.ui.module;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;
import top.r3944realms.docchecktoolrefactored.System;
import top.r3944realms.docchecktoolrefactored.core.MD5HashCalculator;
import top.r3944realms.docchecktoolrefactored.ui.SceneManager;
import top.r3944realms.docchecktoolrefactored.ui.task.HashFileGenerationTask;
import top.r3944realms.docchecktoolrefactored.ui.utils.DialogUtil;
import top.r3944realms.docchecktoolrefactored.util.LoggerMarker;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
//TODO: 应该交给Platform:runLater;
@Slf4j
public class StorageCarrierPaneController {

    @FXML
    private Button caculateHash7B;

    @FXML
    private Button generateHashFile7B;

    @FXML
    private TextField loadCompressedFile;

    @FXML
    private TextField loadDigitalOutcomes;

    @FXML
    private TextArea result7TA;

    @FXML
    private Button selectLoadCompressedFile7B;

    @FXML
    private Button selectLoadDigitalOutcomes7B;

    @FXML
    private Button clearSelectedFoldersButton;

    // 保存按钮原始文本，用于状态恢复
    private final String calculateHashOriginalText = "计算哈希值";
    private final String generateHashOriginalText = "生成哈希值表文件";

    private final top.r3944realms.docchecktoolrefactored.ui.utils.ProgressBar progressBar = new top.r3944realms.docchecktoolrefactored.ui.utils.ProgressBar(false);
    @FXML
    void onSelectLD(ActionEvent event) {
        log.info(LoggerMarker.DEBUG_MARKER, "用户点击选择文件夹按钮");
        DirectoryChooser directoryChooser = System.getDirectoryChooser();
        directoryChooser.setTitle("选择要检查的文件夹(页面级文件夹和文件级文件夹等不包括目录文件夹）");

        File selectedFolder = directoryChooser.showDialog(new Stage());
        if (selectedFolder != null) {
            System.setLastModifiedFile(selectedFolder);
            String currentText = loadDigitalOutcomes.getText();
            String folderPath = selectedFolder.getAbsolutePath();

            // 如果当前文本框为空，直接设置；否则追加路径
            if (currentText == null || currentText.isEmpty()) {
                loadDigitalOutcomes.setText(folderPath);
            } else {
                // 检查是否已经添加过该路径，避免重复
                String[] existingPaths = currentText.split(File.pathSeparator);
                boolean alreadyExists = false;
                for (String path : existingPaths) {
                    if (path.equals(folderPath)) {
                        alreadyExists = true;
                        break;
                    }
                }

                if (!alreadyExists) {
                    loadDigitalOutcomes.setText(currentText + File.pathSeparator + folderPath);
                }
            }

            log.info(LoggerMarker.DEBUG_MARKER, "用户选择了文件夹: {}", selectedFolder.getAbsolutePath());

            // 添加成功样式
            applySuccessStyle(loadDigitalOutcomes);
        } else {
            log.info(LoggerMarker.DEBUG_MARKER, "用户取消了文件夹选择");
        }
    }

    @FXML
    void onClearSelectedFolders(ActionEvent event) {
        log.info(LoggerMarker.DEBUG_MARKER, "用户点击清除已选择文件夹按钮");
        loadDigitalOutcomes.setText("");
        result7TA.setText("已清除所有已选择的文件夹");
        log.info(LoggerMarker.DEBUG_MARKER, "已清除所有已选择的文件夹");

        // 移除样式
        resetStyle(loadDigitalOutcomes);
    }




    @FXML
    void onSelectLC(ActionEvent event) {
        log.info(LoggerMarker.DEBUG_MARKER, "用户点击选择RAR文件按钮");
        FileChooser fileChooser = System.getFileChooser();
        fileChooser.setTitle("选择一个 .rar 文件");
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("RAR Files", "*.rar"));
        File selectedFile = fileChooser.showOpenDialog(new Stage());
        if (selectedFile != null) {
            System.setLastModifiedFile(selectedFile);
            loadCompressedFile.setText(selectedFile.getAbsolutePath());
            log.info(LoggerMarker.DEBUG_MARKER, "用户选择了RAR文件: {}", selectedFile.getAbsolutePath());

            // 添加成功样式
            applySuccessStyle(loadCompressedFile);
        } else {
            log.info(LoggerMarker.DEBUG_MARKER, "用户取消了RAR文件选择");
        }

    }

    @FXML
    void onCaculateHash(ActionEvent event) {
        generateHashFile7B.setDisable(true);
        String filePath = loadCompressedFile.getText();
        if (filePath == null || filePath.isEmpty()) {
            log.warn(LoggerMarker.DEBUG_MARKER, "未选择RAR文件，无法计算哈希值");
            result7TA.setText("请先选择一个 .rar 文件");
            DialogUtil.showWarningDialog("警告", "操作有误", "请先选择一个 .rar 文件");
            generateHashFile7B.setDisable(false);
            // 重置样式
            return;
        }

        File file = new File(filePath);
        if (!file.exists() || !file.isFile() || !filePath.endsWith(".rar")) {
            log.warn(LoggerMarker.DEBUG_MARKER, "选择的文件无效或不是RAR文件: {}", filePath);
            result7TA.setText("所选文件不存在或不是一个有效的 .rar 文件");
            DialogUtil.showWarningDialog("警告", "操作有误", "所选文件不存在或不是一个有效的 .rar 文件");
            generateHashFile7B.setDisable(false);
            return;
        }
        try {
            // 添加加载样式
            applyLoadingStyle(generateHashFile7B, "处理中...");
            log.info(LoggerMarker.DEBUG_MARKER, "开始计算RAR文件MD5哈希值: {}", filePath);
            MD5HashCalculator hashCalculator = new MD5HashCalculator();
            String hashResult = hashCalculator.calculateHash(file.toPath());
            result7TA.setText("计算结果：\n" + hashResult);
            applySuccessStyle(result7TA);
            generateHashFile7B.setDisable(false);
            log.info(LoggerMarker.DEBUG_MARKER, "文件哈希值计算完成: {}", hashResult);
            log.info(LoggerMarker.RELEASE_MARKER, "文件哈希值计算完成.\t{}文件的哈希值： {}", filePath,hashResult);
        } catch (IOException e) {
            log.error(LoggerMarker.DEBUG_MARKER, "计算文件哈希值时出错: {}", filePath, e);
            DialogUtil.showDetailedErrorDialog("错误", "生成哈希文件时出错：", e.getMessage());
            generateHashFile7B.setDisable(false);
            // 重置样式
            resetButtonStyle(generateHashFile7B, generateHashOriginalText);
            result7TA.setText("计算哈希值时出错: " + e.getMessage());
        }
    }

    @FXML
    void onGenerateHF(ActionEvent event) {
        caculateHash7B.setDisable(true);

        String folderPathsText = loadDigitalOutcomes.getText();
        if (folderPathsText == null || folderPathsText.isEmpty()) {
            log.warn(LoggerMarker.DEBUG_MARKER, "未选择文件夹，无法生成哈希列表文件");
            DialogUtil.showWarningDialog("警告", "操作有误", "请先选择一个文件夹");
            result7TA.setText("请先选择一个文件夹");
            caculateHash7B.setDisable(false);
            return;
        }
        log.info(LoggerMarker.DEBUG_MARKER, "开始生成哈希列表文件");
        // 解析多个文件夹路径
        String[] folderPaths = folderPathsText.split(File.pathSeparator);
        List<File> folders = new ArrayList<>();

        for (String path : folderPaths) {
            File folder = new File(path.trim());
            if (folder.exists() && folder.isDirectory()) {
                folders.add(folder);
            } else {
                log.warn(LoggerMarker.DEBUG_MARKER, "选择的路径无效或不是文件夹: {}", path);
                result7TA.setText("所选路径不存在或不是一个有效的文件夹: " + path);
                DialogUtil.showWarningDialog("警告", "操作有误", ("所选路径不存在或不是一个有效的文件夹: " + path));
                caculateHash7B.setDisable(false);
                return;
            }
        }
        applyLoadingStyle(caculateHash7B, "处理中...");
        FileChooser fileChooser = System.getFileChooser();
        fileChooser.setTitle("选择保存哈希列表文件的位置");
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("CSV Files", "*.csv"));

        // 设置默认文件名
        fileChooser.setInitialFileName(System.getProjectInfo().makeProjectInfoIntoFileNamePrefix() + "-哈希值列表文件.csv");

        // 使用当前窗口作为父窗口显示文件选择对话框
        File outputFile = fileChooser.showSaveDialog(selectLoadDigitalOutcomes7B.getScene().getWindow());

        if (outputFile == null) {
            log.info(LoggerMarker.DEBUG_MARKER, "用户取消了文件保存操作");
            result7TA.setText("未选择保存位置");
            DialogUtil.showWarningDialog("警告", "操作有误", "未选择保存位置");
            return;
        }

        // 正确处理文件扩展名 - 只有在没有.csv扩展名时才添加
        final File finalOutputFile;
        if (!outputFile.getName().toLowerCase().endsWith(".csv")) {
            finalOutputFile = new File(outputFile.getAbsolutePath() + ".csv");
        } else {
            finalOutputFile = outputFile;
        }

        log.info(LoggerMarker.DEBUG_MARKER, "选择的输出文件路径: {}", finalOutputFile.getAbsolutePath());
        progressBar.showProgress(SceneManager.getPrimaryStage(), "生成哈希值列表文件", "正在初始化...");
        // 创建后台任务
        Task<String> task = new HashFileGenerationTask(finalOutputFile, folders);
        // 绑定任务属性到UI
        ChangeListener<Number> progressChangeListener = (obs, oldVal, newVal) -> {
            if (newVal != null) {
                if (task.getMessage() != null) {
                    progressBar.updateProgress(newVal.doubleValue(), task.getMessage());
                }
            }
        };
        task.progressProperty().addListener(progressChangeListener);
        // 绑定任务的消息到结果文本区域，实时显示进度
//        ChangeListener<String> messageChangeListener = (observable, oldValue, newValue) -> {
//            result7TA.setText(newValue);
//        };
//        task.messageProperty().addListener(messageChangeListener);

        // 任务成功完成
        task.setOnSucceeded(e -> {
            progressBar.closeProgress();
            log.info(LoggerMarker.DEBUG_MARKER, "哈希文件生成任务成功完成");
            caculateHash7B.setDisable(false);
            applySuccessStyle(result7TA);
            resetButtonStyle(caculateHash7B, calculateHashOriginalText);
            result7TA.setText(task.getValue());
            log.info(LoggerMarker.RELEASE_MARKER,  task.getValue());
        });

        // 任务失败处理
        task.setOnFailed(e -> {
            progressBar.closeProgress();
            Throwable exception = task.getException();
            task.progressProperty().removeListener(progressChangeListener);
//            task.messageProperty().removeListener(messageChangeListener);
            caculateHash7B.setDisable(false);
            String errorMsg = "生成哈希文件时出错: " + (exception != null ? exception.getMessage() : "未知错误");
            applyErrorStyle(result7TA);
            DialogUtil.showDetailedErrorDialog("错误", "生成哈希文件时出错", errorMsg);
            resetButtonStyle(caculateHash7B, calculateHashOriginalText);
            log.error(LoggerMarker.RELEASE_MARKER, "哈希文件生成任务失败", exception);
            result7TA.setText(errorMsg);
        });

        // 任务取消处理
        task.setOnCancelled(e -> {
            progressBar.closeProgress();
            task.progressProperty().removeListener(progressChangeListener);
//            task.messageProperty().removeListener(messageChangeListener);
            caculateHash7B.setDisable(false);
            resetStyle(result7TA);
            resetButtonStyle(caculateHash7B, calculateHashOriginalText);
            log.info(LoggerMarker.DEBUG_MARKER, "哈希文件生成任务被用户取消");
            result7TA.setText("哈希文件生成操作已取消");
        });

        // 在新线程中执行任务
        Thread thread = new Thread(task);
        thread.setDaemon(true);
        thread.start();
    }
    // ======================== 提取的样式变更方法 ========================
    // 样式控制工具方法
    private void applyLoadingStyle(Button button, String text) {
        Platform.runLater(() -> {
            button.setText(text);
            button.getStyleClass().add("loading");
        });
    }

    private void resetButtonStyle(Button button, String originalText) {
        Platform.runLater(() -> {
            button.setText(originalText);
            button.getStyleClass().remove("loading");
        });
    }

    private void applySuccessStyle(TextField textField) {
        Platform.runLater(() -> {
            textField.getStyleClass().remove("error");
            textField.getStyleClass().add("success");
        });
    }

    private void applySuccessStyle(TextArea textArea) {
        Platform.runLater(() -> {
            textArea.getStyleClass().removeAll("error");
            textArea.getStyleClass().add("success");
        });
    }

    private void applyErrorStyle(TextArea textArea) {
        Platform.runLater(() -> {
            textArea.getStyleClass().removeAll("success");
            textArea.getStyleClass().add("error");
        });
    }


    private void resetStyle(TextField textField) {
        Platform.runLater(() -> {
            textField.getStyleClass().removeAll("success", "error");
        });
    }

    private void resetStyle(TextArea textArea) {
        Platform.runLater(() -> {
            textArea.getStyleClass().removeAll("success", "error");
        });
    }
    // ====================================================================
}
