package com.ecep.contract.task;

import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.StringUtils;

import com.ecep.contract.CompanyFileType;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.constant.CompanyConstant;
import com.ecep.contract.service.CompanyFileService;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.vo.CompanyFileVo;
import com.ecep.contract.vo.CompanyOldNameVo;
import com.ecep.contract.vo.CompanyVo;

import lombok.Getter;
import lombok.Setter;

/**
 * 公司文件重置任务类
 * 用于本地执行公司文件重置操作，不通过WebSocket调用远程服务
 */
public class CompanyFileResetTasker extends Tasker<Boolean> {
    @Getter
    @Setter
    private CompanyVo company;

    @Getter
    @Setter
    private boolean filesUpdated = false;

    private CompanyFileService getCompanyFileService() {
        return getCachedBean(CompanyFileService.class);
    }

    private CompanyOldNameService getCompanyOldNameService() {
        return getCachedBean(CompanyOldNameService.class);
    }

    @Override
    protected Boolean execute(MessageHolder holder) throws Exception {
        updateTitle("重置公司文件");
        updateProgress(0, 100);

        if (company == null) {
            holder.error("公司对象为空");
            updateProgress(100, 100);
            return false;
        }

        try {
            holder.info("开始重置公司文件：" + company.getName());
            updateProgress(10, 100);

            boolean result = reBuildingFiles(company, holder);

            if (result) {
                holder.info("公司文件重置成功");
                setFilesUpdated(true);
            } else {
                holder.info("公司文件重置完成，但没有更新任何文件");
                setFilesUpdated(false);
            }

            updateProgress(100, 100);
            return result;
        } catch (Exception e) {
            holder.error("公司文件重置失败：" + e.getMessage());
            updateProgress(100, 100);
            throw e;
        }
    }

    public boolean reBuildingFiles(CompanyVo company, MessageHolder holder) {
        CompanyFileService companyFileService = getCompanyFileService();
        boolean modfied = false;
        List<CompanyFileVo> dbFiles = companyFileService.findByCompany(company);
        holder.debug("现有 " + dbFiles.size() + " 条文件记录");

        Map<String, CompanyFileVo> map = new HashMap<>();
        // 排除掉数据库中重复的
        for (CompanyFileVo dbFile : dbFiles) {
            String filePath = dbFile.getFilePath();
            // 没有文件信息，无效记录，删除
            if (!StringUtils.hasText(filePath)) {
                companyFileService.delete(dbFile);
                holder.info("删除无效记录：" + filePath);
                modfied = true;
                continue;
            }

            // 目录不存在，删除
            File dir = new File(filePath);
            if (!dir.exists()) {
                companyFileService.delete(dbFile);
                holder.info("删除不存在目录记录：" + filePath);
                modfied = true;
                continue;
            }

            CompanyFileVo old = map.put(filePath, dbFile);
            // 目录有重复删除
            if (old != null) {
                companyFileService.delete(old);
                holder.info("删除重复目录记录：" + filePath);
                modfied = true;
            }
        }

        Map<String, File> directoryMap = new HashMap<>();

        // 公司目录
        if (StringUtils.hasText(company.getPath())) {
            File dir = new File(company.getPath());
            directoryMap.put(company.getName(), dir);
        }

        // 获取所有曾用名
        List<CompanyOldNameVo> oldNames = getCompanyOldNameService().findAllByCompany(company);
        for (CompanyOldNameVo companyOldName : oldNames) {
            String path = companyOldName.getPath();
            if (StringUtils.hasText(path)) {
                File dir = new File(path);
                directoryMap.put(companyOldName.getName(), dir);
            }
        }

        for (Map.Entry<String, File> entry : directoryMap.entrySet()) {
            String companyName = entry.getKey();
            File dir = entry.getValue();
            if (!StringUtils.hasText(companyName)) {
                continue;
            }
            if (dir == null || !dir.exists()) {
                continue;
            }

            File[] files = dir.listFiles();
            if (files == null) {
                // 文件系统出错或者没有相关文件
                continue;
            }
            holder.debug("目录 " + companyName + " 下有 " + files.length + " 个文件");
            for (File file : files) {
                // 只处理文件
                if (!file.isFile() || FileUtils.isHiddenFile(file)) {
                    continue;
                }
                String filePath = file.getAbsolutePath();
                if (!map.containsKey(filePath)) {
                    // 未记录
                    CompanyFileVo filled = fillFileType(file, holder);
                    filled.setCompanyId(company.getId());
                    companyFileService.save(filled);
                    holder.info("导入 " + file.getName() + " ");
                    modfied = true;
                }
            }
        }
        return modfied;
    }

    /**
     * 从文件名生成公司文件对象，文件已经存在公司对应的存储目录下
     *
     * @param file   文件
     * @param holder 状态输出
     * @return 公司文件对象
     */
    private CompanyFileVo fillFileType(File file, MessageHolder holder) {
        String fileName = file.getName();
        CompanyFileVo companyFile = new CompanyFileVo();
        companyFile.setType(CompanyFileType.General);
        companyFile.setFilePath(file.getAbsolutePath());
        fillApplyDateAndExpiringDateAbsent(file, companyFile);

        // 天眼查 基础版企业信用报告
        if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_BASIC_REPORT)
                || fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_MAJOR_REPORT)
                || fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_ANALYSIS_REPORT)) {
            companyFile.setType(CompanyFileType.CreditReport);
            fillExpiringDateAbsent(companyFile);
            return companyFile;
        }

        // 天眼查 企业信用信息公示报告
        if (fileName.contains(CloudServiceConstant.TYC_ENTERPRISE_CREDIT_REPORT)) {
            companyFile.setType(CompanyFileType.CreditInfoPublicityReport);
            return companyFile;
        }

        // 集团相关方平台 元素征信 企业征信报告
        if (fileName.contains(CloudServiceConstant.RK_VENDOR_NAME)
                && fileName.contains(CloudServiceConstant.RK_ENTERPRISE_CREDIT_REPORT)) {
            companyFile.setType(CompanyFileType.CreditReport);
            fillExpiringDateAbsent(companyFile);
            return companyFile;
        }

        // 营业执照
        if (fileName.contains(CompanyConstant.BUSINESS_LICENSE)) {
            companyFile.setType(CompanyFileType.BusinessLicense);
            return companyFile;
        }

        // 其他企业信用报告
        if (fileName.contains(CompanyConstant.ENTERPRISE_REPORT)) {
            companyFile.setType(CompanyFileType.CreditReport);
            fillExpiringDateAbsent(companyFile);
            return companyFile;
        }
        return companyFile;
    }

    /**
     * 补齐有效期
     */
    private void fillExpiringDateAbsent(CompanyFileVo file) {
        LocalDate expiringDate = file.getExpiringDate();
        if (expiringDate == null) {
            LocalDate applyDate = file.getApplyDate();
            if (applyDate != null) {
                expiringDate = applyDate.plusYears(1);
                file.setExpiringDate(expiringDate);
            }
        }
    }

    private static void fillApplyDateAndExpiringDateAbsent(File file, CompanyFileVo companyFile) {
        LocalDate applyDate = companyFile.getApplyDate();
        if (applyDate != null) {
            return;
        }

        String fileName = file.getName();
        Pattern pattern = Pattern.compile(MyDateTimeUtils.REGEX_DATE);
        Matcher matcher = pattern.matcher(fileName);
        while (matcher.find()) {
            // 找到第一个日期，记作起始日期
            String date = matcher.group();
            try {
                LocalDate n = LocalDate.parse(date);
                companyFile.setApplyDate(n);

                // 如果 截至日期未设置，则第二个日期记作截至日期（如有）
                LocalDate expiringDate = companyFile.getExpiringDate();
                if (expiringDate == null) {
                    while (matcher.find()) {
                        date = matcher.group();
                        try {
                            n = LocalDate.parse(date);
                            companyFile.setExpiringDate(n);
                            break;
                        } catch (Exception ignored) {
                        }
                    }
                }
                break;
            } catch (Exception ignored) {
            }
        }

    }
}