package com.ecep.contract.ds.contract.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.List;

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

import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.ds.project.service.DeliverySignMethodService;
import com.ecep.contract.ds.project.service.ProductTypeService;
import com.ecep.contract.ds.project.service.ProjectCostItemService;
import com.ecep.contract.ds.project.service.ProjectCostService;
import com.ecep.contract.ds.project.service.ProjectIndustryService;
import com.ecep.contract.ds.project.service.ProjectService;
import com.ecep.contract.ds.project.service.ProjectTypeService;
import com.ecep.contract.ds.project.service.SaleTypeService;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.ProductType;
import com.ecep.contract.model.Project;
import com.ecep.contract.model.ProjectCost;
import com.ecep.contract.model.ProjectCostItem;
import com.ecep.contract.model.ProjectIndustry;
import com.ecep.contract.model.ProjectSaleType;
import com.ecep.contract.model.ProjectType;
import com.ecep.contract.ui.Tasker;

import lombok.Getter;
import lombok.Setter;

/**
 * 合同成本审批表更新任务
 * 成本审批表为Excel文件，默认更新 #matchedSheetName（成本） sheet，如果没有匹配名称的sheet，则尝试使用第一个sheet
 *
 */
public class CustomerContractCostFormUpdateTask extends Tasker<Object> {
    private static final Logger logger = LoggerFactory.getLogger(CustomerContractCostFormUpdateTask.class);

    /**
     * 对应的合同
     */
    @Getter
    @Setter
    private Contract contract;
    /**
     * 成本表文件名
     */
    @Setter
    private String fileName;
    /**
     * 模板文件名
     */
    @Setter
    private String template;
    /**
     * 填写日期
     */
    @Setter
    private LocalDate applyDate;
    /**
     * 目标文件
     */
    private File destFile;


    /**
     * 用于匹配成本审批表的Sheet名字，第一包含字符的sheet为要更新的sheet
     */
    @Setter
    private String matchedSheetName = "成本";
    @Setter
    private ProjectService projectService;
    @Setter
    private ProjectTypeService projectTypeService;
    @Setter
    private SaleTypeService saleTypeService;
    @Setter
    private ProjectIndustryService projectIndustryService;
    @Setter
    private ProductTypeService productTypeService;
    @Setter
    private DeliverySignMethodService deliverySignMethodService;
    @Setter
    private ProjectCostService costService;
    @Setter
    private ProjectCostItemService costItemService;

    private ProjectService getProjectService() {
        if (projectService == null) {
            projectService = SpringApp.getBean(ProjectService.class);
        }
        return projectService;
    }

    private ProjectTypeService getProjectTypeService() {
        if (projectTypeService == null) {
            projectTypeService = SpringApp.getBean(ProjectTypeService.class);
        }
        return projectTypeService;
    }

    private SaleTypeService getSaleTypeService() {
        if (saleTypeService == null) {
            saleTypeService = SpringApp.getBean(SaleTypeService.class);
        }
        return saleTypeService;
    }

    private ProjectIndustryService getProjectIndustryService() {
        if (projectIndustryService == null) {
            projectIndustryService = SpringApp.getBean(ProjectIndustryService.class);
        }
        return projectIndustryService;
    }

    private ProductTypeService getProductTypeService() {
        if (productTypeService == null) {
            productTypeService = SpringApp.getBean(ProductTypeService.class);
        }
        return productTypeService;
    }

    private DeliverySignMethodService getDeliverySignMethodService() {
        if (deliverySignMethodService == null) {
            deliverySignMethodService = SpringApp.getBean(DeliverySignMethodService.class);
        }
        return deliverySignMethodService;
    }

    private ProjectCostService getCostService() {
        if (costService == null) {
            costService = SpringApp.getBean(ProjectCostService.class);
        }
        return costService;
    }
    private ProjectCostItemService getCostItemService() {
        if (costItemService == null) {
            costItemService = SpringApp.getBean(ProjectCostItemService.class);
        }
        return costItemService;
    }

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

    private void updateCostForm(MessageHolder holder) {
        if (!StringUtils.hasText(contract.getPath())) {
            holder.error("供应商目录未设置，请先设置供应商目录");
            return;
        }

        File templateFile = new File(template);
        if (!templateFile.exists()) {
            holder.warn("评价表模板文件 " + templateFile.getAbsolutePath() + " 不存在，请检查");
            return;
        }
        String template_file_name = templateFile.getName();
        File dir = new File(contract.getPath());

        destFile = new File(dir, fileName);
        if (destFile.exists()) {
            holder.debug("表单文件已经存在，尝试更新...");
            try (
                    InputStream inp = new FileInputStream(destFile);
                    Workbook wb = WorkbookFactory.create(inp)
            ) {
                updateCustomerContractCost(wb, holder);
                holder.info(fileName + "已更新");
            } catch (Exception e) {
                holder.error(e.getMessage());
                logger.error(e.getMessage(), e);
            }
        } else {
            holder.debug("根据模板 " + template_file_name + " 创建表单 " + destFile.getName());
            try (
                    InputStream inp = new FileInputStream(template);
                    Workbook wb = WorkbookFactory.create(inp)
            ) {
                updateCustomerContractCost(wb, holder);
                holder.info(fileName + "已更新");
            } catch (Exception e) {
                holder.error(e.getMessage());
                logger.error(e.getMessage(), e);
            }
        }

    }

    private void updateCustomerContractCost(
            Workbook wb,
            MessageHolder holder) throws IOException {

        Sheet sheet = null;
        if (StringUtils.hasText(matchedSheetName)) {
            for (Sheet v : wb) {
                if (v.getSheetName().contains(matchedSheetName)) {
                    sheet = v;
                    break;
                }
            }
            if (sheet == null) {
                holder.error("检查模板文件，找不到成本页");
                return;
            }
        } else {
            sheet = wb.getSheetAt(0);
        }

        updateCustomerContractCost(sheet);

        // 输出到文件
        try (OutputStream fileOut = new FileOutputStream(destFile)) {
            wb.write(fileOut);

        } catch (FileNotFoundException e) {
            holder.error("写文件时发生错误：" + e.getMessage());
            logger.error(e.getMessage(), e);
        }
    }

    private void updateCustomerContractCost(Sheet sheet) {
        // 项目名
        String projectName = contract.getName();
        Project project = contract.getProject();
        //销售类型
        ProjectSaleType saleType = null;
        // 项目类型
        ProjectType projectType = null;
        // 使用场所
        ProjectIndustry industry = null;
        // 销售类别
        ProductType productType = null;
        // 项目地址
        String address = null;
        if (project != null) {
            if (!Hibernate.isInitialized(project)) {
                project = getProjectService().findById(project.getId());
                contract.setProject(project);
            }
            projectName = project.getName();

            saleType = project.getSaleType();
            if (saleType != null) {
                if (!Hibernate.isInitialized(saleType)) {
                    saleType = getSaleTypeService().findById(saleType.getId());
                    project.setSaleType(saleType);
                }
            }

            projectType = project.getProjectType();
            if (projectType != null) {
                if (!Hibernate.isInitialized(projectType)) {
                    projectType = getProjectTypeService().findById(projectType.getId());
                    project.setProjectType(projectType);
                }
            }

            industry = project.getIndustry();
            if (industry != null) {
                if (!Hibernate.isInitialized(industry)) {
                    industry = getProjectIndustryService().findById(industry.getId());
                    project.setIndustry(industry);
                }
            }

            productType = project.getProductType();
            if (productType != null) {
                if (!Hibernate.isInitialized(productType)) {
                    productType = getProductTypeService().findById(productType.getId());
                    project.setProductType(productType);
                }

            }

            address = project.getAddress();
        }

        // 项目名称
        setCellValue(sheet, "C5", projectName);

        setCellValue(sheet, "M5", saleType == null ? "" : saleType.getName());
        setCellValue(sheet, "I5", projectType == null ? "" : projectType.getName());
        setCellValue(sheet, "M6", industry == null ? "" : industry.getName());
        setCellValue(sheet, "I6", productType == null ? "" : productType.getName());

        setCellValue(sheet, "C7", address);


        // 买方
        Company company = contract.getCompany();
        if (company != null) {
            if (!Hibernate.isInitialized(company)) {
                company = getCompanyService().findById(company.getId());
                contract.setCompany(company);
            }
            setCellValue(sheet, "C6", company.getName());
        }

        // 销售员
        Employee employee = contract.getEmployee();
        if (employee != null) {
            if (!Hibernate.isInitialized(employee)) {
                employee = getEmployeeService().findById(employee.getId());
                contract.setEmployee(employee);
            }
            setCellValue(sheet, "M7", employee.getName());
        }


        float taxAndSurcharges = 11;
        ProjectCost cost = getCostService().findByContract(contract);
        if (cost != null) {
            taxAndSurcharges = cost.getTaxAndSurcharges();
            if (cost.getApplyTime() != null) {
                applyDate = cost.getApplyTime().toLocalDate();
            }
        }
        setCellValue(sheet, "D40", taxAndSurcharges + "%");

        float stampTax = 0.03f;
        setCellValue(sheet, "D39", stampTax + "%");

        List<ProjectCostItem> items = getCostItemService().findByCost(cost);
        for (int i = 0; i < items.size(); i++) {
            ProjectCostItem item = items.get(i);
            int row = 10 + i;
            setCellValue(sheet, row, 0, item.getTitle());
            setCellValue(sheet, row, 2, item.getSpecification());
            setCellValue(sheet, row, 3, item.getInQuantity());
            setCellValue(sheet, row, 4, item.getOutExclusiveTaxPrice());
            setCellValue(sheet, row, 6, item.getOutTaxRate() / 100);
            setCellValue(sheet, row, 8, item.getInExclusiveTaxPrice());
            setCellValue(sheet, row, 10, item.getInTaxRate() / 100);
        }

        if (applyDate != null) {
            setCellValue(sheet, "I7", applyDate);
        }

    }


}
