package com.ecep.contract.service.tasker;

import static com.ecep.contract.util.ExcelUtils.setCellValue;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;

import com.ecep.contract.CustomerFileType;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.cloud.tyc.CloudTycService;
import com.ecep.contract.ds.customer.service.CompanyCustomerEvaluationFormFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.ds.other.model.CloudTyc;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
import com.ecep.contract.ds.customer.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.ui.Tasker;
import com.ecep.contract.util.CompanyUtils;
import com.fasterxml.jackson.databind.JsonNode;

public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> implements WebSocketServerTasker {
    private CompanyCustomer customer;

    @Override
    public void init(JsonNode argsNode) {
        int customerId = argsNode.get(0).asInt();
        customer = getCachedBean(CompanyCustomerService.class).getById(customerId);
    }

    CompanyCustomerFileService getCompanyCustomerFileService() {
        return getCachedBean(CompanyCustomerFileService.class);
    }

    CompanyCustomerEvaluationFormFileService getCompanyCustomerEvaluationFormFileService() {
        return getCachedBean(CompanyCustomerEvaluationFormFileService.class);
    }

    @Override
    protected Object execute(MessageHolder holder) throws Exception {
        updateEvaluationForm(holder);
        return null;
    }

    public void updateEvaluationForm(MessageHolder holder) {
        if (!StringUtils.hasText(customer.getPath())) {
            holder.error("供应商目录未设置，请先设置供应商目录");
            return;
        }
        File template = getCompanyCustomerFileService().getEvaluationFormTemplate();
        if (template == null) {
            holder.error("评价表模板文件未设置，请先设置评价表模板文件");
            return;
        }
        if (!template.exists()) {
            holder.error("评价表模板文件 " + template.getAbsolutePath() + " 不存在，请检查");
            return;
        }

        updateProgress(1, 10);
        File dir = new File(customer.getPath());
        String template_file_name = template.getName();
        File destFile = new File(dir, template_file_name);

        if (destFile.exists()) {
            holder.info("表单文件已经存在，" + destFile.getName());
            try (
                    InputStream inp = new FileInputStream(destFile);
                    Workbook wb = WorkbookFactory.create(inp)) {
                updateEvaluationForm(wb, destFile, holder);
                holder.info("评价表已更新");
            } catch (Exception e) {
                holder.error(e.getMessage());
            }
        } else {
            holder.info("根据模板 " + template_file_name + " 创建表单 " + destFile.getName());
            try (InputStream inp = new FileInputStream(template); Workbook wb = WorkbookFactory.create(inp)) {
                updateEvaluationForm(wb, destFile, holder);
                holder.info("评价表已创建");
                CompanyCustomerFile customerFile = new CompanyCustomerFile();
                customerFile.setCustomer(customer);
                customerFile.setFilePath(destFile.getAbsolutePath());
                customerFile.setType(CustomerFileType.General);
                getCompanyCustomerFileService().save(customerFile);
            } catch (Exception e) {
                holder.error(e.getMessage());
            }
        }
        updateProgress(10, 10);
    }

    /**
     * 更新客户评估表，依据模板创建，如果已经存在生成的文件，则更新评估表
     *
     * @param wb       work book
     * @param destFile 目标文件
     */
    public void updateEvaluationForm(Workbook wb, File destFile, MessageHolder holder) throws IOException {
        updateProgress(2, 10);
        Company company = customer.getCompany();
        if (!Hibernate.isInitialized(company)) {
            company = getCompanyService().getById(company.getId());
            customer.setCompany(company);
        }
        Sheet sheet = wb.getSheetAt(0);
        updateSheet(company, sheet, holder.sub(" - "));
        updateProgress(8, 10);
        // 输出到文件
        try (OutputStream fileOut = new FileOutputStream(destFile)) {
            wb.write(fileOut);
        } catch (FileNotFoundException e) {
            holder.error("写评估表时发生文件错误，请检查评估表是否被打开中:" + e.getMessage());
        }
    }

    private void updateSheet(Company company, Sheet sheet, MessageHolder holder) {
        setCellValue(sheet, "B3", "客户编号：" + CompanyUtils.formatCompanyVendorId(customer.getId()));
        setCellValue(sheet, "B4", "客户名称：" + company.getName());

        LocalDate suggestDate = getCompanyCustomerFileService().getNextSignDate(customer, holder);
        if (suggestDate == null) {
            suggestDate = LocalDate.now();
        }
        setCellValue(sheet, "H3", "评定时间：" + suggestDate);
        setCellValue(sheet, "H4", "统一社会信用代码：");
        setCellValue(sheet, "H5", company.getUniscid());
        // 注册所属地
        setCellValue(sheet, "B5", "注册所属地：" + company.getDistrict());
        // 经营状态
        setCellValue(sheet, "D6", "经营状态：" + company.getEntStatus());
        // 成立日期
        setCellValue(sheet, "H6", "成立日期：" + company.getSetupDate());
        // 所属行业
        setCellValue(sheet, "D7", "所属行业：" + company.getIndustry());
        setCellValue(sheet, "D8",
                "注册资金：" + company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency());
        // 企业类型
        setCellValue(sheet, "H10", "企业类型：" + company.getEntType());
        // 天眼评分
        CloudTycService cloudTycService = SpringApp.getBean(CloudTycService.class);
        CloudTyc cloudTyc = cloudTycService.getOrCreateCloudTyc(company);
        setCellValue(sheet, "D10", "天眼评分：" + (cloudTyc.getScore() > 0 ? cloudTyc.getScore() : ""));

        // 检索评估表
        List<CompanyCustomerFile> customerFiles = getCompanyCustomerFileService().findAllByCustomerAndType(customer,
                CustomerFileType.EvaluationForm);

        List<CompanyCustomerEvaluationFormFile> filteredList = customerFiles.stream().filter(file -> {
            return file.getSignDate() != null && file.isValid();
        })
                .sorted(Comparator.comparing(CompanyCustomerFile::getSignDate))
                .map(getCompanyCustomerEvaluationFormFileService()::findByCustomerFile)
                .toList();

        if (filteredList.isEmpty()) {
            setCellValue(sheet, "C40", "首次评价");
            try {
                sheet.addMergedRegion(CellRangeAddress.valueOf("C40:K40"));
            } catch (Exception ignored) {
            }
        } else {
            holder.info("客户有 " + filteredList.size() + " 条评价表");
            setCellValue(sheet, "C40", "评价日期");
            try {
                sheet.addMergedRegion(CellRangeAddress.valueOf("C40:D40"));
            } catch (Exception ignored) {
            }
            setCellValue(sheet, "E40", "经济指标");
            setCellValue(sheet, "F40", "综合指标");
            setCellValue(sheet, "G40", "资信等级");
            String[] CreditLevelTitles = new String[] { "-", "差★", " 一般★★", " 较好★★★", " 好★★★★", " " };
            int baseRow = 40;
            for (CompanyCustomerEvaluationFormFile form : filteredList) {
                CompanyCustomerFile customerFile = form.getCustomerFile();
                if (!Hibernate.isInitialized(customerFile)) {
                    customerFile = getCompanyCustomerFileService().findById(customerFile.getId());
                }
                setCellValue(sheet, baseRow, 2, String.valueOf(customerFile.getSignDate()));
                setCellValue(sheet, baseRow, 4, form.getCatalog());
                setCellValue(sheet, baseRow, 5, form.getLevel());
                if (form.getCreditLevel() == null) {
                    setCellValue(sheet, baseRow, 6, "-");
                } else {
                    setCellValue(sheet, baseRow, 6, CreditLevelTitles[form.getCreditLevel()]);
                }
                try {
                    sheet.addMergedRegion(new CellRangeAddress(baseRow, baseRow, 2, 3));
                } catch (Exception ignored) {
                }
                baseRow++;
            }
        }
    }
}
