package com.ecep.contract.controller.tab;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.util.StringUtils;
import org.w3c.dom.html.HTMLDocument;

import com.ecep.contract.DesktopUtils;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.controller.company.AbstCompanyBasedTabSkin;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.model.CloudRk;
import com.ecep.contract.model.CloudTyc;
import com.ecep.contract.model.CloudYu;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyExtendInfo;
import com.ecep.contract.service.CloudRkService;
import com.ecep.contract.service.CloudTycService;
import com.ecep.contract.service.CompanyExtendInfoService;
import com.ecep.contract.service.YongYouU8Service;
import com.ecep.contract.util.DelayOnceExecutor;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CloudRkViewModel;
import com.ecep.contract.vm.CloudTycInfoViewModel;
import com.ecep.contract.vm.CloudYuInfoViewModel;
import com.ecep.contract.vm.CompanyExtendInfoViewModel;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Tab;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.Border;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;
import lombok.Setter;

@FxmlPath("/ui/company/company-tab-other.fxml")
public class CompanyTabSkinOther
        extends AbstCompanyBasedTabSkin
        implements TabSkin {
    private static final Logger logger = LoggerFactory.getLogger(CompanyTabSkinOther.class);
    /**
     * 以下是云平台数据
     */
    public TitledPane rkCloudPane;
    public TextField cloudRkIdField;
    public TextField cloudRkCloudIdField;
    public TextField cloudRkLatestField;
    public TextField cloudRkCustomerGradeField;
    public TextField cloudRkCustomerScoreField;
    public TextField cloudRkCustomerDescriptionField;

    public TextField cloudRkVendorGradeField;
    public TextField cloudRkVendorScoreField;
    public TextField cloudRkVendorDescriptionField;

    public TextField cloudRkBlackListUpdatedField;
    public TextField cloudRkCloudLatestField;
    public TextField cloudRkEntUpdateField;
    public TextField cloudRkCreditRankField;
    public TextField cloudRkCreditRankDescriptionField;
    public Label cloudRkVersionLabel;
    public CheckBox cloudRkAutoUpdateField;

    // Tyc //
    public TitledPane tycCloudPane;
    public TextField cloudTycIdField;
    public TextField cloudTycCloudIdField;
    public TextField cloudTycLatestField;
    public Label cloudTycVersionLabel;
    public TextField tycCloudPaneCloudScore;
    // public Hyperlink tycCloudPaneHyperLink;
    public Button tycCloudPaneSaveButton;

    // Yu //
    public TitledPane yuCloudPane;
    public TextField cloudYuIdField;
    public TextField cloudYuCloudIdField;
    public TextField cloudYuLatestField;
    public Label cloudYuVersionLabel;
    public Button yuCloudPaneSaveButton;

    // Extend Info //
    public TitledPane extendInfoPane;
    public TextField extendInfoIdField;
    public TextField extendInfoLatestField;
    public Label extendInfoVersionLabel;
    public CheckBox extendInfoDisableVerifyField;
    public Button extendInfoPaneSaveButton;

    private final CloudRkViewModel rkCloudInfoViewModel = new CloudRkViewModel();
    private final CloudTycInfoViewModel tycCloudInfoViewModel = new CloudTycInfoViewModel();
    private final CloudYuInfoViewModel yuCloudInfoViewModel = new CloudYuInfoViewModel();
    private final CompanyExtendInfoViewModel extendInfoViewModel = new CompanyExtendInfoViewModel();

    @Setter
    private CloudRkService cloudRkService;
    @Setter
    private CloudTycService cloudTycService;
    @Setter
    private YongYouU8Service yongYouU8Service;
    @Setter
    private CompanyExtendInfoService extendInfoService;

    public CompanyTabSkinOther(CompanyWindowController controller) {
        super(controller);
    }

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

    @Override
    public void initializeTab() {
        initializeCloudRkPane();
        initializeCloudTycPane();
        initializeCloudYuPane();
        initializeExtendInfoPane();
        listenTabSelectionChanged();
    }

    @Override
    public void onTabShown() {
        Company parent = getEntity();
        updateRKCloudPane(parent, rkCloudPane);
        updateTYCCloudPane(parent, tycCloudPane);
        updateYuCloudPane(parent, yuCloudPane);
        updateExtendInfoPane(parent, extendInfoPane);
    }

    /**
     * 初始化 相关方平台信息 Titled Pane
     */
    private void initializeCloudRkPane() {
        // 记录编号
        cloudRkIdField.textProperty().bind(rkCloudInfoViewModel.getId().asString());
        // 平台编号
        cloudRkCloudIdField.textProperty().bindBidirectional(rkCloudInfoViewModel.getCloudId());
        cloudRkLatestField.textProperty().bind(rkCloudInfoViewModel.getLatestUpdate().map(MyDateTimeUtils::format));
        cloudRkVersionLabel.textProperty().bind(rkCloudInfoViewModel.getVersion().asString("Ver:%s"));

        cloudRkAutoUpdateField.selectedProperty().bindBidirectional(rkCloudInfoViewModel.getAutoUpdate());

        cloudRkCustomerGradeField.textProperty().bind(rkCloudInfoViewModel.getCustomerGrade());
        cloudRkCustomerScoreField.textProperty().bind(rkCloudInfoViewModel.getCustomerScore().asString());
        cloudRkCustomerDescriptionField.textProperty().bind(rkCloudInfoViewModel.getCustomerDescription());

        cloudRkVendorGradeField.textProperty().bind(rkCloudInfoViewModel.getVendorGrade());
        cloudRkVendorScoreField.textProperty().bind(rkCloudInfoViewModel.getVendorScore().asString());
        cloudRkVendorDescriptionField.textProperty().bind(rkCloudInfoViewModel.getVendorDescription());

        cloudRkCreditRankField.textProperty().bind(rkCloudInfoViewModel.getRank());
        cloudRkCreditRankDescriptionField.textProperty().bind(rkCloudInfoViewModel.getRankDescription());
        cloudRkCloudLatestField.textProperty().bind(rkCloudInfoViewModel.getCloudLatest().map(MyDateTimeUtils::format));
        cloudRkEntUpdateField.textProperty()
                .bind(rkCloudInfoViewModel.getCloudEntUpdate().map(MyDateTimeUtils::format));
        cloudRkBlackListUpdatedField.textProperty()
                .bind(rkCloudInfoViewModel.getCloudBlackListUpdated().map(MyDateTimeUtils::format));

        DelayOnceExecutor saveExecutor = new DelayOnceExecutor(() -> {
            save(rkCloudInfoViewModel);
            cloudRkAutoUpdateField.setBorder(null);
        }, 2, TimeUnit.SECONDS).exception(e -> logger.error(e.getMessage(), e));
        cloudRkAutoUpdateField.setOnMouseClicked(event -> {
            cloudRkAutoUpdateField.setBorder(Border.stroke(Color.RED));
            saveExecutor.tick();
        });
    }

    public void save(CloudRkViewModel viewModel) {
        int infoId = viewModel.getId().get();
        CloudRkService service = getCloudRkService();
        CloudRk cloudRk = service.findById(infoId);
        if (cloudRk == null) {
            throw new RuntimeException("CloudRk not found");
        }
        if (viewModel.copyTo(cloudRk)) {
            CloudRk saved = service.save(cloudRk);
            if (Platform.isFxApplicationThread()) {
                viewModel.update(saved);
            } else {
                Platform.runLater(() -> {
                    viewModel.update(saved);
                });
            }
        }
    }

    /**
     * 杂项页中，集团相关方panel中更新action
     */
    public void onCloudRkUpdateButtonClickedAction(ActionEvent event) {
        Button button = (Button) event.getSource();
        button.setDisable(true);
        CompletableFuture.runAsync(() -> {
            try {
                onCloudRkUpdateButtonClicked(event);
            } catch (Exception e) {
                UITools.showExceptionAndWait("", e);
            }
        }).whenComplete((v, e) -> {
            button.setDisable(false);
        });
    }

    /**
     * 从集团相关方平台中更新公司信息
     *
     * @see #onCloudRkUpdateButtonClickedAction(ActionEvent)
     */
    private void onCloudRkUpdateButtonClicked(ActionEvent actionEvent) throws IOException {
        Button button = (Button) actionEvent.getSource();
        Company company = getEntity();
        MessageHolder holder = (level, message) -> {
            setStatus(message);
            if (level == Level.WARNING) {
                logger.warn("{} {}", getEntity().getName(), message);
            }
            if (level == Level.SEVERE) {
                logger.error("{} {}", getEntity().getName(), message);
            }
        };

        CloudRk cloudRk = getCloudRkService().updateCloudRk(company, holder);
        Platform.runLater(() -> {
            rkCloudInfoViewModel.update(cloudRk);
        });
    }

    private CloudRkService.EntInfo showEnterpriseChooser(List<CloudRkService.EntInfo> entInfos) {
        // TODO 转换为 独立窗口类，通过 getResult() 返回操作
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setWidth(350);
        alert.setHeaderText(CloudServiceConstant.RK_NAME + " 返回多个结果, 请选择确认");
        ListView<CloudRkService.EntInfo> listView = new ListView<>();
        listView.setCellFactory(param -> new ListCell<>() {
            @Override
            protected void updateItem(CloudRkService.EntInfo item, boolean empty) {
                super.updateItem(item, empty);
                if (item == null || empty) {
                    setText(null);
                    // setBackground(Background.EMPTY);
                } else {
                    setText((item.isNowName() ? "☑" : "☐") + " " + item.getName());
                }

            }
        });
        listView.getItems().addAll(entInfos);
        alert.getDialogPane().setContent(listView);
        if (alert.showAndWait().get() != ButtonType.OK) {
            return null;
        }
        return listView.getSelectionModel().getSelectedItem();
    }

    public void onTycCloudPaneHyperLinkClickedAction(ActionEvent event) {
        String cloudId = tycCloudInfoViewModel.getCloudId().get();
        String url = null;
        if (StringUtils.hasText(cloudId)) {
            url = String.format(CloudServiceConstant.TYC_URL_COMPANY, cloudId);
        } else {
            Company company = getEntity();
            url = String.format(CloudServiceConstant.TYC_URL_COMPANY_SEARCH, company.getName());
        }
        DesktopUtils.showInBrowse(url);
    }

    public void onTycCloudPaneHyperLinkInnerViewClickedAction(ActionEvent event) {
        Company company = getEntity();
        String cloudId = tycCloudInfoViewModel.getCloudId().get();

        String url = String.format(CloudServiceConstant.TYC_URL_COMPANY_SEARCH, company.getName());
        Stage stage = new Stage();
        WebView webView = new WebView();
        webView.getEngine().locationProperty().addListener((ob, old, n) -> {
            System.out.println("location " + old + " -> " + n);
        });
        webView.getEngine().getLoadWorker().exceptionProperty().addListener((ob, old, n) -> {
            System.out.println("LoadWorker exception:" + n);
        });
        webView.getEngine().setCreatePopupHandler(p -> {
            System.out.println("Popup = " + p);
            return webView.getEngine();
        });

        webView.getEngine().setPromptHandler(p -> {
            System.out.println("Prompt = " + p);
            return null;
        });

        webView.getEngine().setConfirmHandler(p -> {
            System.out.println("Confirm = " + p);
            return null;
        });
        webView.getEngine().getLoadWorker().stateProperty().addListener((ob, old, n) -> {
            System.out.println("LoadWorker state:" + n);
        });
        webView.getEngine().getLoadWorker().progressProperty().addListener((ob, old, n) -> {
            System.out.println("LoadWorker progress:" + n);
        });

        File directory = new File(".");
        System.out.println(". = " + directory.getAbsolutePath());
        webView.getEngine().setUserDataDirectory(directory);

        webView.getEngine().load(url);
        webView.getEngine().documentProperty().addListener(((observable, oldValue, newValue) -> {
            if (newValue == null) {
                return;
            }
            HTMLDocument doc = (HTMLDocument) newValue;
            setStatus("Open Url : " + doc.getURL());
            stage.setTitle(doc.getTitle());
            // updateByTycSearch(company, doc);
        }));
        StackPane root = new StackPane();
        root.getChildren().add(webView);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    /**
     * 杂项 天眼查页，更新按钮 action
     */
    public void onCloudTycUpdateButtonClickedAction(ActionEvent event) {
        Button button = (Button) event.getSource();
        button.setDisable(true);
        CompletableFuture.runAsync(() -> {
            try {
                onCloudTycUpdateButtonClicked(event);
            } catch (Exception e) {
                UITools.showExceptionAndWait("", e);
            }
        }).whenComplete((v, e) -> {
            button.setDisable(false);
        });
    }

    /**
     * 更新 天眼查 资讯资信
     *
     * @see #onCloudTycUpdateButtonClickedAction(ActionEvent)
     */
    private void onCloudTycUpdateButtonClicked(ActionEvent event) {
        // TODO 待实现
        setStatus("待实现");
        // CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS).execute(() -> {
        // button.setDisable(false);
        // });
    }

    /**
     * 初始化 天眼查平台 Titled Pane
     */
    private void initializeCloudTycPane() {
        // 记录编号
        cloudTycIdField.textProperty().bind(tycCloudInfoViewModel.getId().asString());
        // 平台编号
        cloudTycCloudIdField.textProperty().bindBidirectional(tycCloudInfoViewModel.getCloudId());
        cloudTycLatestField.textProperty().bind(tycCloudInfoViewModel.getLatest().map(MyDateTimeUtils::format));
        cloudTycVersionLabel.textProperty().bind(tycCloudInfoViewModel.getVersion().asString("Ver:%s"));

        TextField cloudIdField = cloudTycCloudIdField;
        TextField cloudScoreField = tycCloudPaneCloudScore;

        DelayOnceExecutor saveExecutor = new DelayOnceExecutor(() -> {
            cloudTycService.save(tycCloudInfoViewModel);
            cloudIdField.setBorder(null);
            cloudScoreField.setBorder(null);
            tycCloudPaneSaveButton.setDisable(true);
            setStatus("保存成功");
        }, 2, TimeUnit.SECONDS).exception(e -> logger.error(e.getMessage(), e));

        cloudIdField.setOnKeyPressed(event -> {
            cloudIdField.setBorder(Border.stroke(Color.RED));
            tycCloudPaneSaveButton.setDisable(false);
            saveExecutor.tick();
        });
        cloudScoreField.setOnKeyPressed(event -> {
            cloudScoreField.setBorder(Border.stroke(Color.RED));
            tycCloudPaneSaveButton.setDisable(false);
            saveExecutor.tick();
        });

        cloudScoreField.textProperty().bindBidirectional(tycCloudInfoViewModel.getScore(), new NumberStringConverter());
        tycCloudPaneSaveButton.setOnAction(event -> {
            saveExecutor.tickNow();
        });
    }

    private void initializeCloudYuPane() {
        try {
            yongYouU8Service = getBean(YongYouU8Service.class);
        } catch (BeansException e) {
            yuCloudPane.setDisable(true);
        }

        cloudYuIdField.textProperty().bind(yuCloudInfoViewModel.getId().asString());
        cloudYuCloudIdField.textProperty().bindBidirectional(yuCloudInfoViewModel.getCloudId());
        cloudYuLatestField.textProperty().bind(yuCloudInfoViewModel.getLatest().map(MyDateTimeUtils::format));
        cloudYuVersionLabel.textProperty().bind(yuCloudInfoViewModel.getVersion().asString("Ver:%s"));

        Button button = yuCloudPaneSaveButton;

        // 更新
        button.setOnAction(event -> {
            button.setDisable(true);
            CompletableFuture.runAsync(() -> {
                try {
                    onCloudYuUpdateButtonClicked(event);
                } catch (Exception e) {
                    UITools.showExceptionAndWait("", e);
                }
            }).whenComplete((v, e) -> {
                button.setDisable(false);
            });
        });

    }

    private void onCloudYuUpdateButtonClicked(ActionEvent event) {
        Company company = getEntity();
        // service.syncVendor(company);

    }

    private void initializeExtendInfoPane() {
        // 记录编号
        extendInfoIdField.textProperty().bind(extendInfoViewModel.getId().asString());
        extendInfoDisableVerifyField.selectedProperty().bindBidirectional(extendInfoViewModel.getDisableVerify());
        extendInfoVersionLabel.textProperty().bind(extendInfoViewModel.getVersion().asString("Ver:%s"));

        DelayOnceExecutor saveExecutor = new DelayOnceExecutor(() -> {
            save(extendInfoViewModel);
            extendInfoDisableVerifyField.setBorder(null);
        }, 2, TimeUnit.SECONDS).exception(e -> logger.error(e.getMessage(), e));
        extendInfoDisableVerifyField.setOnMouseClicked(event -> {
            extendInfoDisableVerifyField.setBorder(Border.stroke(Color.RED));
            saveExecutor.tick();
        });

        extendInfoPaneSaveButton.setOnAction(event -> {
            saveExecutor.tickNow();
        });
    }

    public void save(CompanyExtendInfoViewModel viewModel) {
        int infoId = viewModel.getId().get();
        CompanyExtendInfoService service = getExtendInfoService();
        CompanyExtendInfo cloudRk = service.findById(infoId);
        if (cloudRk == null) {
            throw new RuntimeException("CloudRk not found");
        }
        if (viewModel.copyTo(cloudRk)) {
            CompanyExtendInfo saved = service.save(cloudRk);
            if (Platform.isFxApplicationThread()) {
                viewModel.update(saved);
            } else {
                Platform.runLater(() -> {
                    viewModel.update(saved);
                });
            }
        }
    }

    private void updateRKCloudPane(Company company, TitledPane pane) {
        CloudRkViewModel viewModel = rkCloudInfoViewModel;
        CloudRk cloudRk = getCloudRkService().getOrCreateCloudRk(company);
        Platform.runLater(() -> {
            viewModel.update(cloudRk);
        });
    }

    private void updateTYCCloudPane(Company company, TitledPane pane) {
        CloudTycInfoViewModel viewModel = tycCloudInfoViewModel;
        CloudTyc cloudTyc = getCloudTycService().getOrCreateCloudTyc(company);
        Platform.runLater(() -> {
            viewModel.update(cloudTyc);
        });
    }

    private void updateYuCloudPane(Company company, TitledPane pane) {
        CloudYuInfoViewModel viewModel = yuCloudInfoViewModel;
        if (yongYouU8Service == null) {
            setStatus("未启用 " + CloudServiceConstant.U8_NAME + " 服务");
            return;
        }
        CloudYu cloudYu = yongYouU8Service.getOrCreateCloudYu(company);
        Platform.runLater(() -> {
            viewModel.update(cloudYu);
        });
    }

    private void updateExtendInfoPane(Company company, TitledPane pane) {
        CompanyExtendInfoViewModel viewModel = extendInfoViewModel;
        CompanyExtendInfoService service = getExtendInfoService();
        CompanyExtendInfo extendInfo = service.findByCompany(company);
        Platform.runLater(() -> {
            viewModel.update(extendInfo);
        });
    }

    CloudRkService getCloudRkService() {
        if (cloudRkService == null) {
            cloudRkService = getBean(CloudRkService.class);
        }
        return cloudRkService;
    }

    CloudTycService getCloudTycService() {
        if (cloudTycService == null) {
            cloudTycService = getBean(CloudTycService.class);
        }
        return cloudTycService;
    }

    CompanyExtendInfoService getExtendInfoService() {
        if (extendInfoService == null) {
            extendInfoService = getBean(CompanyExtendInfoService.class);
        }
        return extendInfoService;
    }

    YongYouU8Service getYongYouU8Service() {
        return yongYouU8Service;
    }
}
