package com.ecep.contract.controller.project.quotation;

import static com.ecep.contract.util.ExcelUtils.getCellValue;
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 org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.ecep.contract.MessageHolder;
import com.ecep.contract.constant.ContractConstant;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.Project;
import com.ecep.contract.model.ProjectQuotation;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.task.Tasker;
import com.ecep.contract.util.ProxyUtils;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;

/**
 * 报价审批导出为Excel文件
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class ProjectQuotationExportAsExcelFile extends Tasker<Object> {
    private static final Logger logger = LoggerFactory.getLogger(ProjectQuotationExportAsExcelFile.class);
    private String name = "报价审批表";
    File destFile;

    ProjectQuotation quotation;
    @Setter
    private ProjectService projectService;

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

    @Override
    protected Object execute(MessageHolder holder) throws Exception {
        updateTitle("根据模板导出" + name);

        // \\10.84.209.8\规章制度\ISO9000\01-最新发布版\4_JL_记录文件\ECEP-JL-XS-06-B_项目报价审批表.xlsx
        String path = getConfService().getString(ContractConstant.KEY_QUOTATION_TEMPLATE);
        if (!StringUtils.hasText(path)) {
            holder.error(name + "模板文件未设置，请先设置" + name + "模板文件");
            return null;
        }
        File template = new File(path);
        if (!template.exists()) {
            holder.warn(name + "模板文件 " + template.getAbsolutePath() + " 不存在，请检查");
            return null;
        }

        Project project = quotation.getProject();
        if (!ProxyUtils.isInitialized(project)) {
            project = getProjectService().findById(project.getId());
            quotation.setProject(project);
        }
        File dir = getProjectService().searchPath(project);
        LocalDate thatDay = LocalDate.now();
        if (quotation.getApplyTime() != null) {
            thatDay = quotation.getApplyTime().toLocalDate();
        }
        String filename = name + "_" + thatDay;
        String extension = StringUtils.getFilenameExtension(path);
        File destFile = new File(dir, filename + "." + extension);
        int count = 0;
        while (destFile.exists()) {
            holder.warn(destFile.getName() + " 已存在");
            destFile = new File(dir, filename + "_" + (++count) + "." + extension);
        }
        try (
                InputStream inp = new FileInputStream(template);
                Workbook wb = WorkbookFactory.create(inp)) {
            updateProjectQuotation(wb, destFile, holder);
            holder.info(destFile.getName() + "已创建");
        } catch (Exception e) {
            holder.error(e.getMessage());
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    private void updateProjectQuotation(Workbook wb, File destFile, MessageHolder holder) throws IOException {
        Sheet sheet = null;
        for (int i = 0; i < wb.getNumberOfSheets(); i++) {
            Sheet s = wb.getSheetAt(i);
            if (s.getSheetName().contains(name)) {
                sheet = s;
                break;
            }
        }

        if (sheet == null) {
            holder.error("找不到" + name + "表");
            return;
        }
        holder.info("模板版本：" + getCellValue(sheet, "D1"));

        updateProjectQuotation(sheet, holder);
        // 输出到文件
        try (OutputStream fileOut = new FileOutputStream(destFile)) {
            wb.write(fileOut);
        } catch (FileNotFoundException e) {
            holder.error("写时发生文件错误，请检查文件是否被打开中, " + e.getMessage());
            logger.error(e.getMessage(), e);
        }

    }

    private void updateProjectQuotation(Sheet sheet, MessageHolder holder) {
        updateTitle("更新 " + sheet.getSheetName() + " Sheet");
        Project project = quotation.getProject();
        Employee applicant = quotation.getApplicant();

        if (applicant != null) {
            if (!ProxyUtils.isInitialized(applicant)) {
                applicant = getEmployeeService().findById(applicant.getId());
                project.setApplicant(applicant);
            }
            setCellValue(sheet, "B4", applicant.getName());
        } else {
            setCellValue(sheet, "B4", "");
        }

        setCellValue(sheet, "B5", project.getName());

        Company customer = project.getCustomer();
        if (customer != null) {
            if (!ProxyUtils.isInitialized(customer)) {
                customer = getCompanyService().findById(customer.getId());
                project.setCustomer(customer);
            }
            setCellValue(sheet, "B6", customer.getName());
        } else {
            setCellValue(sheet, "B6", "-");
        }

        String[] labels = new String[] { "较差", "一般", "良好" };
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < labels.length; i++) {
            if (i > 0) {
                sb.append("   ");
            }
            sb.append(labels[i]);
            sb.append(quotation.getLevel() == i ? "☑" : "☐");
        }
        setCellValue(sheet, "B7", sb.toString());

        if (quotation.isStandardPayWay()) {
            setCellValue(sheet, "B8", "标准");
        } else {
            setCellValue(sheet, "B8", "非标准：" + quotation.getNoStandardPayWayText());
        }

        setCellValue(sheet, "B9", quotation.getAmount());
    }
}
