package com.ecep.contract.service.tasker;

import com.ecep.contract.MessageHolder;
import com.ecep.contract.VendorFileType;
import com.ecep.contract.ds.company.service.CompanyContactService;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.vendor.model.Vendor;
import com.ecep.contract.ds.vendor.model.VendorFile;
import com.ecep.contract.ds.vendor.service.VendorFileService;
import com.ecep.contract.ds.vendor.service.VendorService;
import com.ecep.contract.ui.Tasker;
import com.ecep.contract.util.ExcelUtils;
import com.ecep.contract.vo.CompanyContactVo;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.VendorVo;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.poi.ss.usermodel.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;

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

/**
 * 更新供应商评价表
 */
@Component
public class CompanyVendorEvaluationFormUpdateTask extends Tasker<Object> implements WebSocketServerTasker {
    private VendorVo vendor;
    private CompanyVo company;
    private File template;

    @Override
    public void init(JsonNode argsNode) {
        int vendorId = argsNode.get(0).asInt();
        vendor = getVendorService().findById(vendorId);
    }

    private VendorService getVendorService() {
        return getCachedBean(VendorService.class);
    }

    VendorFileService getVendorFileService() {
        return getCachedBean(VendorFileService.class);
    }

    @Override
    protected Object execute(MessageHolder holder) throws Exception {
        if (vendor == null) {
            holder.error("未找到供应商信息");
            return null;
        }
        if (!StringUtils.hasText(vendor.getPath())) {
            holder.error("供应商目录未设置，请先设置供应商目录");
            return null;
        }
        updateEvaluationForm(holder);
        return null;
    }

    public void updateEvaluationForm(MessageHolder holder) {
        company = getCachedBean(CompanyService.class).findById(vendor.getCompanyId());

        template = getVendorFileService().getEvaluationFormTemplate();
        if (template == null) {
            holder.error("评价表模板文件未设置，请先设置评价表模板文件");
            return;
        }
        if (!template.exists()) {
            holder.error("评价表模板文件 " + template.getAbsolutePath() + " 不存在，请检查");
            return;
        }

        updateProgress(1, 10);
        File dir = new File(vendor.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("评价表已创建");
                // 创建 VendorFile 对象
                VendorFile vendorFile = new VendorFile();
                Vendor vendorEntity = getCachedBean(VendorService.class).getById(vendor.getId());
                vendorFile.setVendor(vendorEntity);
                vendorFile.setFilePath(destFile.getAbsolutePath());
                vendorFile.setType(VendorFileType.EvaluationForm);
                vendorFile.setSignDate(LocalDate.now());
                vendorFile.setValid(false);
                getVendorFileService().save(vendorFile);
            } 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);
        Sheet sheet = wb.getSheetAt(0);
        holder.info("更新 " + sheet.getSheetName() + " Sheet");
        updateSheet(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(Sheet sheet, MessageHolder holder) {
        String vendor_id = "" + vendor.getId();
        if (!Objects.equals(vendor_id, getCellValue(sheet, "G1"))) {
            setCellValue(sheet, "G1", vendor_id);
            holder.info("供应商编号更新为：" + vendor_id);
        }

        String companyName = company.getName();
        if (!Objects.equals(companyName, getCellValue(sheet, "B2"))) {
            setCellValue(sheet, "B2", companyName);
            holder.info("供应商名称更新为：" + companyName);
        }

        String address = null;
        // 联系人
        CompanyContactVo contact = null;
        if (vendor.getContactId() != null) {
            contact = getCompanyContactService().findById(vendor.getContactId());
            if (contact != null) {
                holder.debug("供应商指定联系人：" + contact.getName());
            }
        }
        if (contact == null) {
            contact = getCompanyContactService().findFirstByCompany(company);
            if (contact != null) {
                holder.debug("从公司联系人列表中获取联系人：" + contact.getName());
            }
        }
        if (contact != null) {
            String contactName = contact.getName();
            if (!Objects.equals(contactName, getCellValue(sheet, "F2"))) {
                setCellValue(sheet, "F2", contactName);
                holder.info("联系人姓名更新为：" + contactName);
            }
            String contactPhone = contact.getPhone();
            if (StringUtils.hasText(contactPhone)) {
                if (!Objects.equals(contactPhone, getCellValue(sheet, "F3"))) {
                    setCellValue(sheet, "F3", contactPhone);
                    holder.info("联系人电话更新为：" + contactPhone);
                }
            }

            if (StringUtils.hasText(contact.getAddress())) {
                address = contact.getAddress();
            }
        }

        if (!StringUtils.hasText(address)) {
            address = company.getAddress();
            if (StringUtils.hasText(address)) {
                holder.debug("使用公司地址：" + address);
            }
        }
        if (!StringUtils.hasText(address)) {
            address = company.getRegAddr();
            if (StringUtils.hasText(address)) {
                holder.debug("使用公司注册地址：" + address);
            }
        }

        if (StringUtils.hasText(address)) {
            if (!Objects.equals(address, getCellValue(sheet, "B3"))) {
                setCellValue(sheet, "B3", address);
                holder.info("更新供应商地址为：" + address);
            }
        } else {
            holder.warn("没有获取到供应商地址，请检查供应商信息");
        }


        String companyUniscid = company.getUniscid();
        if (!Objects.equals(companyUniscid, getCellValue(sheet, "B8"))) {
            setCellValue(sheet, "B8", companyUniscid);
            holder.info("更新供应商统一社会信用代码为：" + companyUniscid);
        }

        String regCap = company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency();
        if (!Objects.equals(regCap, getCellValue(sheet, "E8"))) {
            setCellValue(sheet, "E8", regCap);
            holder.info("更新供应商注册资金为：" + regCap);
        }

        setCellValue(sheet, "H8", company.getOperationPeriodBegin());
        if (company.getOperationPeriodEnd() == null) {
            if (company.getOperationPeriodBegin() != null) {
                setCellValue(sheet, "H9", "无固定期限");
            }
        } else {
            setCellValue(sheet, "H9", company.getOperationPeriodEnd());
        }

        String vendorPurchase = vendor.getPurchase();
        if (!Objects.equals(vendorPurchase, getCellValue(sheet, "C4"))) {
            setCellValue(sheet, "C4", vendorPurchase);
            holder.info("更新供应商采购内容为：" + vendorPurchase);
        }

        Cell a6 = ExcelUtils.getCell(sheet, "A6");
        if (a6 != null) {
            if (!Objects.equals(a6.getStringCellValue(), vendor.getDescription())) {
                a6.setCellValue(vendor.getDescription());
                holder.info("更新供应商描述为：" + StringUtils.truncate(a6.getStringCellValue(), 30));
            }
            if (a6.getCellStyle().getAlignment() != HorizontalAlignment.LEFT) {
                a6.getCellStyle().setAlignment(HorizontalAlignment.LEFT);
                holder.info("更新供应商描述对齐方式为左对齐");
            }
        }

        // 第一个评价日期
        Cell g16 = ExcelUtils.getCell(sheet, "G16");
        if (g16 == null) {
            holder.error("模板异常, 第一个评价日期单元格(G16)未找到!");
        } else {
            CellType cellType = g16.getCellType();
            // 未设置, 尝试更新
            if (cellType == CellType.BLANK || cellType == CellType.NUMERIC) {
                holder.debug("推算下一个评价日期...");
                LocalDate nextSignDate = getVendorFileService().getNextSignDate(vendor, holder.sub(" -| "));
                // 当没有推荐日期时，说明不需要评价，更新为空
                if (nextSignDate == null) {
                    g16.setBlank();
                    holder.info("!未推算出下一个评价日期，单元格设空!");
                } else {
                    holder.debug("推算出下一个评价日期：" + nextSignDate);
                    LocalDateTime value = g16.getLocalDateTimeCellValue();
                    if (value == null) {
                        g16.setCellValue(nextSignDate);
                        holder.info("评价日期更新为:" + nextSignDate);
                    } else {
                        if (!Objects.equals(value.toLocalDate(), nextSignDate)) {
                            g16.setCellValue(nextSignDate);
                            holder.info("评价日期更新为:" + nextSignDate);
                        }
                    }
                }
            } else {
                holder.warn("第一个评价日期所在单元格 " + g16.getAddress().formatAsR1C1String() + " 的单元格类型未知：" + cellType);
            }
        }
    }

    private CompanyContactService getCompanyContactService() {
        return getCachedBean(CompanyContactService.class);
    }
}
