package com.zhangmeng.online.exam.ui.components;

import com.zhangmeng.online.exam.ui.api.ApiUtils;
import com.zhangmeng.online.exam.ui.api.DataLoad;
import com.zhangmeng.online.exam.ui.components.callBack.PaperViewComponentCallBack;
import com.zhangmeng.online.exam.ui.utils.AlertUtils;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Paint;
import javafx.util.Callback;
import org.casic.javafx.control.PaginationPicker;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 试题展示组件
 *
 * @author zm
 * @date 2025/3/19 12:22
 * @version: 1.0
 */
public class PaperViewComponent extends SplitPane {

    private static final double Default_Width = 20;

    //附加信息
    private Map<String, Object> context = new HashMap<>();

    private VBox vbox;

    private VBox chooseVbox;

    private PaperViewComponentCallBack callBack;

    private TableView<Map<String, SimpleStringProperty>> questionTable;

    private final ObservableList<Map<String, SimpleStringProperty>> questionTable_data = FXCollections.observableArrayList();

    private TableColumn<Map<String, SimpleStringProperty>, String> chooseColumn;

    private TableView<Map<String, SimpleStringProperty>> chooseTable;

    //已选题目列表
    private final ObservableList<Map<String, SimpleStringProperty>> chooseTable_data = FXCollections.observableArrayList();

    private SimpleIntegerProperty SINGLE_CHOICE_SCORE = new SimpleIntegerProperty();//单选题分数

    private SimpleIntegerProperty MULTIPLE_CHOICE_SCORE = new SimpleIntegerProperty();//多选题分数

    private SimpleIntegerProperty JUDGMENT_SCORE = new SimpleIntegerProperty();//判断题分数

    private SimpleIntegerProperty NUMERICAL_SCORE = new SimpleIntegerProperty();//计算题分数

    private SimpleIntegerProperty SHORT_ANSWER_SCORE = new SimpleIntegerProperty();//简答题分数
    private SimpleIntegerProperty Fill_IN_THE_BLANKS = new SimpleIntegerProperty();//填空题分数

    private SimpleIntegerProperty ANSWER_SCORE = new SimpleIntegerProperty();//答题总分

    private PaperResultHeaderComponent hBox;

    public PaperViewComponent(PaperViewComponentCallBack callBack) {
        super();
        setCallBack(callBack);

        initQuestionTable();
        initChooseTable();

        this.setOrientation(Orientation.VERTICAL);
        this.setDividerPositions(0.5);

        this.getItems().add(vbox);
        this.getItems().add(chooseVbox);
    }

    public PaperViewComponent(PaperViewComponentCallBack callBack, Map<String, Object> context) {
        super();

        setContext(context);
        setCallBack(callBack);

        initQuestionTable();
        initChooseTable();

        this.setOrientation(Orientation.VERTICAL);
        this.setDividerPositions(0.5);

        this.getItems().add(vbox);
        this.getItems().add(chooseVbox);
    }

    private void initQuestionTable() {
        vbox = new VBox(5);
        vbox.setAlignment(Pos.CENTER_LEFT);
        vbox.prefHeightProperty().bind(this.heightProperty().divide(2));
        vbox.prefWidthProperty().bind(this.widthProperty());

        ApiUtils.DataView dataView = callBack.loadQuestionData(ApiUtils.PAGE_NUM, ApiUtils.PAGE_SIZE);

        questionTable = new TableView<>();
        questionTable.setItems(questionTable_data);
//        questionTable.setEditable(true);
        questionTable.prefHeightProperty().bind(vbox.heightProperty());
        questionTable.prefWidthProperty().bind(vbox.widthProperty());

        List<String> columns = dataView.getKeys().stream().filter(key -> !key.equals("id")).toList();

        columns.forEach(col -> {
            TableColumn<Map<String, SimpleStringProperty>, String> column = new TableColumn<>(col);
            // 数据绑定‌:ml-citation{ref="1,3" data="citationList"}
            column.setCellValueFactory(new MapValueFactory(col));
            // 启用单元格编辑‌:ml-citation{ref="4,5" data="citationList"}
            column.setCellFactory(TextFieldTableCell.forTableColumn());
            column.prefWidthProperty().bind(questionTable.widthProperty().divide(columns.size()).subtract(Default_Width));
            questionTable.getColumns().add(column);
        });

        //添加按钮
        TableColumn<Map<String, SimpleStringProperty>, String> addColumn = new TableColumn<>("操作");
        addColumn.setCellFactory(new Callback<>() {
            @Override
            public TableCell<Map<String, SimpleStringProperty>, String> call(TableColumn<Map<String, SimpleStringProperty>, String> mapStringTableColumn) {
                return new TableCell<>() {
                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);
                        if (!empty) {
                            HBox hBox = new HBox();
//                            hBox.setPrefHeight(30);
                            hBox.setAlignment(Pos.CENTER);
//                            hBox.setStyle("-fx-background-color: #1094e9");

                            Button button = new Button("添加");
                            button.setTextFill(Paint.valueOf("#1094e9"));

                            TableRow<Map<String, SimpleStringProperty>> row = this.getTableRow();
                            button.setOnAction(new EventHandler<ActionEvent>() {
                                @Override
                                public void handle(ActionEvent event) {
                                    if (row.getItem() != null) {
                                        Platform.runLater(new Runnable() {
                                            @Override
                                            public void run() {

                                                chooseTable_data.add(row.getItem());
                                                questionTable_data.remove(row.getItem());
                                            }
                                        });
                                    }
                                }
                            });
                            hBox.getChildren().addAll(button);
                            this.setGraphic(hBox);
                        } else {
                            this.setGraphic(null);
                        }

                    }
                };
            }
        });
        addColumn.prefWidthProperty().bind(questionTable.widthProperty().divide(columns.size() + 2).subtract(50));
        questionTable.getColumns().add(addColumn);

        questionTable_data.addAll(dataView.getDataList());

        //初始化一个分页
        PaginationPicker paginationPicker = new PaginationPicker();
        paginationPicker.setTotal(dataView.getTotal());//设置总数据量，默认0
        paginationPicker.setPageSize(dataView.getPageSize());//设置每页显示条数，默认30
        paginationPicker.setPageButtonCount(9);//设置页码按钮的数量，默认7，当总页数超过该值时会折叠，大于等于 5 且小于等于 21 的奇数
        paginationPicker.setCurrentPage(dataView.getPageNum());//设置当前选择页码，默认第一页（注意：必须放在所有设置条件之后）。不小于0 并且 不大于总页数
        paginationPicker.setPaginationButtonFontSize(12);//设置分页字体大小，默认10(不小于2)
        //监听点击动作事件
        paginationPicker.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
//                System.out.println("当前选择页码："+paginationPicker.getCurrentPage());
                questionTable_data.clear();
                questionTable_data.addAll(callBack.loadQuestionData(paginationPicker.getCurrentPage(), paginationPicker.getPageSize()).getDataList());
            }
        });
        PaperSearchComponent hBox = new PaperSearchComponent(5);
        hBox.getSearchButton().setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                String searchText = hBox.getQuestionName().get();
                if (searchText == null || searchText.trim().isEmpty()) {
                    AlertUtils.alert_msg("搜索内容不能为空！");
                    return;
                }
                questionTable_data.clear();
                questionTable_data.addAll(callBack.searchQuestionData(searchText, paginationPicker.getCurrentPage(), paginationPicker.getPageSize()).getDataList());
            }
        });
        vbox.setPadding(new Insets(5));
        vbox.getChildren().addAll(hBox, questionTable, paginationPicker);


    }

    private void initChooseTable() {
        chooseVbox = new VBox(5);
        chooseVbox.setStyle("-fx-border-width: 1px; -fx-border-color: #e53030; -fx-border-style: solid;");
        chooseVbox.setAlignment(Pos.CENTER_LEFT);
        chooseVbox.prefHeightProperty().bind(this.heightProperty().divide(2));
        chooseVbox.prefWidthProperty().bind(this.widthProperty());


        ApiUtils.DataView dataView = callBack.loadChooseQuestionData(context, ApiUtils.PAGE_NUM, ApiUtils.PAGE_SIZE);

        chooseTable = new TableView<>();
        chooseTable.setItems(chooseTable_data);
//        chooseTable.setEditable(true);
        chooseTable.prefHeightProperty().bind(chooseVbox.heightProperty());
        chooseTable.prefWidthProperty().bind(chooseVbox.widthProperty());

        List<String> columns = dataView.getKeys().stream().filter(key -> !key.equals("id")).toList();

        columns.forEach(col -> {
            TableColumn<Map<String, SimpleStringProperty>, String> column = new TableColumn<>(col);
            // 数据绑定‌:ml-citation{ref="1,3" data="citationList"}
            column.setCellValueFactory(new MapValueFactory(col));
            // 启用单元格编辑‌:ml-citation{ref="4,5" data="citationList"}
            column.setCellFactory(TextFieldTableCell.forTableColumn());
            column.prefWidthProperty().bind(chooseTable.widthProperty().divide(columns.size()).subtract(Default_Width));
            chooseTable.getColumns().add(column);
        });

        //添加按钮
        TableColumn<Map<String, SimpleStringProperty>, String> addColumn = new TableColumn<>("操作");
        addColumn.setCellFactory(new Callback<>() {
            @Override
            public TableCell<Map<String, SimpleStringProperty>, String> call(TableColumn<Map<String, SimpleStringProperty>, String> mapStringTableColumn) {
                return new TableCell<>() {
                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);
                        if (!empty) {
                            HBox hBox = new HBox();
//                            hBox.setPrefHeight(30);
                            hBox.setAlignment(Pos.CENTER);
//                            hBox.setStyle("-fx-background-color: #1094e9");

                            Button button = new Button("删除");
                            button.setTextFill(Paint.valueOf("#1094e9"));

                            TableRow<Map<String, SimpleStringProperty>> row = this.getTableRow();
                            button.setOnAction(new EventHandler<ActionEvent>() {
                                @Override
                                public void handle(ActionEvent event) {
                                    if (row.getItem() != null) {
                                        Platform.runLater(new Runnable() {
                                            @Override
                                            public void run() {
                                                questionTable_data.add(row.getItem());
                                                chooseTable_data.remove(row.getItem());
                                            }
                                        });
                                    }
                                }
                            });

                            hBox.getChildren().addAll(button);
                            this.setGraphic(hBox);
                        } else {
                            this.setGraphic(null);
                        }

                    }
                };
            }
        });
        addColumn.prefWidthProperty().bind(chooseTable.widthProperty().divide(columns.size() + 2).subtract(50));
        chooseTable.getColumns().add(addColumn);

        chooseTable_data.addAll(dataView.getDataList());

        //初始化一个分页
        PaginationPicker paginationPicker = new PaginationPicker();
        paginationPicker.setTotal(dataView.getTotal());//设置总数据量，默认0
        paginationPicker.setPageSize(dataView.getPageSize());//设置每页显示条数，默认30
        paginationPicker.setPageButtonCount(9);//设置页码按钮的数量，默认7，当总页数超过该值时会折叠，大于等于 5 且小于等于 21 的奇数
        paginationPicker.setCurrentPage(dataView.getPageNum());//设置当前选择页码，默认第一页（注意：必须放在所有设置条件之后）。不小于0 并且 不大于总页数
        paginationPicker.setPaginationButtonFontSize(12);//设置分页字体大小，默认10(不小于2)
        //监听点击动作事件
        paginationPicker.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
//                System.out.println("当前选择页码："+paginationPicker.getCurrentPage());
                chooseTable_data.clear();
                chooseTable_data.addAll(callBack.loadQuestionData(paginationPicker.getCurrentPage(), paginationPicker.getPageSize()).getDataList());
            }
        });

        hBox = new PaperResultHeaderComponent(15);
        hBox.getCommitBtn().setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (chooseTable_data.size() <= 0) {
                    AlertUtils.alert_msg("请先选择试题！");
                    return;
                }
                callBack.commitChooseQuestion(context, chooseTable_data);
                chooseTable_data.clear();
                questionTable_data.clear();
                new Thread(() -> {
                    chooseTable_data.addAll(callBack.loadChooseQuestionData(context, ApiUtils.PAGE_NUM, ApiUtils.PAGE_SIZE).getDataList());
                    questionTable_data.addAll(callBack.loadQuestionData(ApiUtils.PAGE_NUM, ApiUtils.PAGE_SIZE).getDataList());
                }).start();
            }
        });
        chooseVbox.setPadding(new Insets(5));
        chooseVbox.getChildren().addAll(hBox, chooseTable, paginationPicker);


        chooseTable_data.addListener(new ListChangeListener<>() {
            @Override
            public void onChanged(Change<? extends Map<String, SimpleStringProperty>> change) {
                //计算分值
                scoreFlush((ObservableList<Map<String, SimpleStringProperty>>) change.getList());
            }
        });

        initScore();

    }

    private void scoreFlush(ObservableList<Map<String, SimpleStringProperty>> changeList) {

        //初始化分值
        SINGLE_CHOICE_SCORE.set(0);
        MULTIPLE_CHOICE_SCORE.set(0);
        JUDGMENT_SCORE.set(0);
        NUMERICAL_SCORE.set(0);
        SHORT_ANSWER_SCORE.set(0);
        Fill_IN_THE_BLANKS.set(0);

        reloadData(changeList);
    }

    private void reloadData(List<Map<String, SimpleStringProperty>> changeList) {
        for (Map<String, SimpleStringProperty> chooseTableDatum : changeList) {
            int score = 0;

            if (chooseTableDatum.get("score").get() != null){
                score = Integer.parseInt(chooseTableDatum.get("score").get());
            }

            SimpleStringProperty type = chooseTableDatum.get("type");

            switch (type.get()) {
                case "单选题" -> SINGLE_CHOICE_SCORE.set(SINGLE_CHOICE_SCORE.get() + score);
                case "多选题" -> MULTIPLE_CHOICE_SCORE.set(MULTIPLE_CHOICE_SCORE.get() + score);
                case "判断题" -> JUDGMENT_SCORE.set(JUDGMENT_SCORE.get() + score);
                case "计算题" -> NUMERICAL_SCORE.set(NUMERICAL_SCORE.get() + score);
                case "填空题" -> Fill_IN_THE_BLANKS.set(Fill_IN_THE_BLANKS.get() + score);
                case "简答题" -> SHORT_ANSWER_SCORE.set(SHORT_ANSWER_SCORE.get() + score);
                default -> throw new IllegalStateException("Unexpected value: " + type.get());
            }
        }

        //计算总分
        ANSWER_SCORE.set(
                SINGLE_CHOICE_SCORE.get()
                        + MULTIPLE_CHOICE_SCORE.get()
                        + JUDGMENT_SCORE.get()
                        + NUMERICAL_SCORE.get()
                        + SHORT_ANSWER_SCORE.get()
                        + Fill_IN_THE_BLANKS.get()

        );

        hBox.setSINGLE_CHOICE_SCORE("单选题分数：" + SINGLE_CHOICE_SCORE.get());
        hBox.setMULTIPLE_CHOICE_SCORE("多选题分数：" + MULTIPLE_CHOICE_SCORE.get());
        hBox.setJUDGMENT_SCORE("判断题分数：" + JUDGMENT_SCORE.get());
        hBox.setNUMERICAL_SCORE("计算题分数：" + NUMERICAL_SCORE.get());
        hBox.setSHORT_ANSWER_SCORE("简答题分数：" + SHORT_ANSWER_SCORE.get());
        hBox.setFill_IN_THE_BLANKS("填空题分数：" + Fill_IN_THE_BLANKS.get());
        hBox.setANSWER_SCORE("答题总分：" + ANSWER_SCORE.get());
    }

    private void initScore() {
        reloadData(chooseTable_data);
    }


    public TableView<Map<String, SimpleStringProperty>> getQuestionTable() {
        return questionTable;
    }

    public void setQuestionTable(TableView<Map<String, SimpleStringProperty>> questionTable) {
        this.questionTable = questionTable;
    }

    public TableView<Map<String, SimpleStringProperty>> getChooseTable() {
        return chooseTable;
    }

    public void setChooseTable(TableView<Map<String, SimpleStringProperty>> chooseTable) {
        this.chooseTable = chooseTable;
    }

    public ObservableList<Map<String, SimpleStringProperty>> getQuestionTable_data() {
        return questionTable_data;
    }

    public PaperViewComponentCallBack getCallBack() {
        return callBack;
    }

    public void setCallBack(PaperViewComponentCallBack callBack) {
        this.callBack = callBack;
    }

    public ObservableList<Map<String, SimpleStringProperty>> getChooseTable_data() {
        return chooseTable_data;
    }

    public VBox getVbox() {
        return vbox;
    }

    public void setVbox(VBox vbox) {
        this.vbox = vbox;
    }


    public VBox getChooseVbox() {
        return chooseVbox;
    }

    public void setChooseVbox(VBox chooseVbox) {
        this.chooseVbox = chooseVbox;
    }

    public Map<String, Object> getContext() {
        return context;
    }

    public void setContext(Map<String, Object> context) {
        this.context = context;
    }
}
