package com.spider.quartz.task;

import com.spider.quartz.config.BaiduAiTranslationService;
import com.spider.quartz.domain.UsUnqualifiedGoods;
import com.spider.quartz.domain.UsUnqualifiedGoodsZh;
import com.spider.quartz.mapper.UsUnqualifiedGoodsMapper;
import com.spider.quartz.mapper.UsUnqualifiedGoodsZhMapper;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 美国CPSC不合格商品 处理CSV文件
 * 优化：基于召回时间的增量导入
 */
@Component
public class CpscCsvProcessor {

    @Autowired
    private UsUnqualifiedGoodsMapper usUnqualifiedGoodsMapper;

    @Autowired
    private UsUnqualifiedGoodsZhMapper usUnqualifiedGoodsZhMapper;

    @Autowired
    private BaiduAiTranslationService baiduTranslationService; // 注入翻译服务

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat CSV_DATE_FORMAT = new SimpleDateFormat("dd-MMM-yy", Locale.US);

    private int successCount = 0;
    private int failureCount = 0;
    private int skippedCount = 0;
    private int emptyNameCount = 0;
    private int emptyRecallTimeCount = 0;
    private int timeConditionSkippedCount = 0;

    /**
     * 处理CSV文件 - 主入口方法
     */
    public void processCsvFile(File csvFile) {
        // 重置计数器
        resetCounters();

        try {
            System.out.println("开始处理CSV文件: " + csvFile.getAbsolutePath());

            // 1. 解析CSV文件
            List<CSVRecord> csvRecords = parseCsvFile(csvFile);
            if (csvRecords.isEmpty()) {
                System.err.println("CSV文件解析结果为空");
                return;
            }

            System.out.println("CSV文件解析成功，共 " + csvRecords.size() + " 条记录");

            // 2. 获取数据库中最新的召回时间
            Date latestRecallTime = getLatestRecallTimeFromDatabase();
            System.out.println("数据库最新召回时间: " +
                    (latestRecallTime != null ? DATE_FORMAT.format(latestRecallTime) : "无数据"));

            // 3. 处理每条记录
            processCsvRecords(csvRecords, csvFile.getAbsolutePath(), latestRecallTime);

            // 4. 输出处理结果
            printProcessResult(csvRecords.size());

        } catch (Exception e) {
            System.err.println("处理CSV文件失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 重置计数器
     */
    private void resetCounters() {
        successCount = 0;
        failureCount = 0;
        skippedCount = 0;
        emptyNameCount = 0;
        emptyRecallTimeCount = 0;
        timeConditionSkippedCount = 0;
    }

    /**
     * 从数据库获取最新的召回时间
     */
    private Date getLatestRecallTimeFromDatabase() {
        try {
            return usUnqualifiedGoodsMapper.selectLatestSpiderTime();
        } catch (Exception e) {
            System.err.println("查询最新召回时间失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 解析CSV文件
     */
    private List<CSVRecord> parseCsvFile(File csvFile) {
        List<CSVRecord> records = new ArrayList<>();
        try (Reader reader = new FileReader(csvFile);
             CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT
                     .withFirstRecordAsHeader()
                     .withIgnoreHeaderCase()
                     .withTrim()
                     .withQuote('"')  // 明确指定引号字符
                     .withIgnoreEmptyLines()
                     .withIgnoreSurroundingSpaces())) {

            for (CSVRecord record : csvParser) {
                records.add(record);
            }

            System.out.println("成功解析 " + records.size() + " 条CSV记录");
            // 打印所有可用的列名
            Map<String, Integer> headerMap = csvParser.getHeaderMap();
            System.out.println("CSV文件头信息: " + headerMap.keySet());

            // 打印前几条记录用于调试
            printSampleRecordsForDebug(records);

        } catch (Exception e) {
            System.err.println("CSV解析失败: " + e.getMessage());
            e.printStackTrace();
        }
        return records;
    }

    /**
     * 打印样本记录用于调试
     */
    private void printSampleRecordsForDebug(List<CSVRecord> records) {
        System.out.println("=== 前5条记录样本 ===");
        for (int i = 0; i < Math.min(5, records.size()); i++) {
            CSVRecord record = records.get(i);
            System.out.println("记录 " + (i + 1) + ":");
            System.out.println("  Name of product: " + getCsvValue(record, "Name of product"));
            System.out.println("  Date: " + getCsvValue(record, "Date"));
            System.out.println("  Name of product: " + getCsvValue(record, "Name of product"));
            System.out.println("---");
        }
        System.out.println("=== 样本记录结束 ===");
    }

    /**
     * 处理CSV记录列表 - 基于召回时间的增量导入
     */
    private void processCsvRecords(List<CSVRecord> csvRecords, String csvFilePath, Date latestRecallTime) {
        int processedCount = 0;
        boolean hasExistingData = (latestRecallTime != null);

        System.out.println("开始处理CSV记录，现有数据: " + (hasExistingData ? "是" : "否"));

        for (int i = 0; i < csvRecords.size(); i++) {
            CSVRecord record = csvRecords.get(i);
            try {
                String recallHeading = getCsvValue(record, "Name of product");
                String recallDate = getCsvValue(record, "Date");

                System.out.println("处理记录 " + (i + 1) + "/" + csvRecords.size() +
                        " - 召回标题: " + (recallHeading != null ? recallHeading.substring(0, Math.min(recallHeading.length(), 50)) : "NULL") +
                        " - 召回日期: " + (recallDate != null ? recallDate : "NULL"));

                // 检查是否应该处理该记录
                boolean shouldProcess = shouldProcessCsvRecord(record, latestRecallTime, hasExistingData);

                if (shouldProcess) {
                    boolean result = saveCsvDataToDatabase(record, csvFilePath);
                    if (result) {
                        successCount++;
                        processedCount++;
                        System.out.println("✅ 成功保存记录");
                    } else {
                        failureCount++;
                        System.err.println("❌ 保存记录失败");
                    }
                } else {
                    skippedCount++;
                    System.out.println("⏭️  跳过记录");
                }
            } catch (Exception e) {
                failureCount++;
                System.err.println("处理CSV记录失败: " + e.getMessage());
                e.printStackTrace();
            }
        }

        System.out.println("记录处理完成 - 成功: " + processedCount + " 条，失败: " + failureCount + " 条，跳过: " + skippedCount + " 条");
    }

    /**
     * 检查是否应该处理CSV记录 - 基于召回时间的增量导入逻辑
     */
    private boolean shouldProcessCsvRecord(CSVRecord record, Date latestRecallTime, boolean hasExistingData) {
        try {
            // 1. 检查商品名称是否为空 - 增强调试
            String goodsName = getCsvValue(record, "Name of product");
            System.out.println("  商品名称检查: '" + (goodsName != null ? goodsName : "NULL") + "'");

            if (goodsName == null || goodsName.trim().isEmpty()) {
                System.out.println("  跳过: 商品名称为空");
                emptyNameCount++;
                return false;
            }

            // 2. 提取召回日期 - 增强调试
            Date recallDate = extractRecallDateFromCsv(record);
            System.out.println("  召回日期检查: " + (recallDate != null ? DATE_FORMAT.format(recallDate) : "NULL"));

            if (recallDate == null) {
                System.out.println("  跳过: 无召回日期");
                emptyRecallTimeCount++;
                return false;
            }

            // 如果数据库中没有数据，处理所有记录（全量导入）
            if (!hasExistingData) {
                System.out.println("  全量模式: 处理所有记录");
                return true;
            }

            // 增量导入：只处理召回时间大于最新时间的记录
            boolean shouldProcess = recallDate.after(latestRecallTime);
            if (shouldProcess) {
                System.out.println("  处理: 召回日期 " + DATE_FORMAT.format(recallDate) +
                        " > 最新日期 " + DATE_FORMAT.format(latestRecallTime));
            } else {
                System.out.println("  跳过: 召回日期 " + DATE_FORMAT.format(recallDate) +
                        " <= 最新日期 " + DATE_FORMAT.format(latestRecallTime));
                timeConditionSkippedCount++;
            }

            return shouldProcess;

        } catch (Exception e) {
            System.err.println("检查记录处理条件失败: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 从CSV记录中提取召回日期 - 只从 Date 字段获取
     */
    private Date extractRecallDateFromCsv(CSVRecord record) {
        try {
            String recallDateStr = getCsvValue(record, "Date");
            if (recallDateStr == null || recallDateStr.isEmpty()) {
                return null;
            }

            // 尝试多种日期格式
            String[] dateFormats = {
                    "MMMM dd, yyyy",  // "January 30, 2025"
                    "dd-MMM-yy",      // "30-Jan-25"
                    "MM/dd/yyyy",     // "01/30/2025"
                    "yyyy-MM-dd"      // "2025-01-30"
            };

            for (String format : dateFormats) {
                try {
                    SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.US);
                    Date recallDate = dateFormat.parse(recallDateStr);
                    System.out.println("  成功解析日期 '" + recallDateStr + "' 为格式: " + format);
                    return recallDate;
                } catch (Exception e) {
                    // 继续尝试下一种格式
                }
            }

            System.out.println("  所有日期格式解析失败: " + recallDateStr);
            return null;

        } catch (Exception e) {
            System.err.println("提取召回日期失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 保存CSV数据到数据库
     */
    private boolean saveCsvDataToDatabase(CSVRecord record, String csvFilePath) {
        try {
            UsUnqualifiedGoods goods = new UsUnqualifiedGoods();
            // 1. 设置基础字段 - 商品名称只从 Name of product 获取
            setBasicCsvFields(goods, record);
            // 验证必要字段
            if (goods.getGoodsName() == null || goods.getGoodsName().trim().isEmpty()) {
                System.err.println("商品名称为空，跳过此记录");
                return false;
            }

            // 2. 设置风险相关字段
            setRiskCsvFields(goods, record);

            // 3. 设置召回相关信息
            setRecallCsvFields(goods, record);

            // 4. 设置其他字段
            setOtherCsvFields(goods, record, csvFilePath);

            int result = usUnqualifiedGoodsMapper.insertUsUnqualifiedGoods(goods);
            if(result > 0){
                //翻译，翻译后保存到zh表
                translateGoodsFields(goods);
            }
            return result > 0;

        } catch (Exception e) {
            System.err.println("保存CSV数据到数据库失败: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 设置基础字段 - CSV版本
     */
    private void setBasicCsvFields(UsUnqualifiedGoods goods, CSVRecord record) {
        // 商品名称只从 Name of product 获取
        goods.setGoodsName(cleanFieldValue(getCsvValue(record, "Name of product")));
        goods.setProducers(cleanFieldValue(getCsvValue(record, "Manufacturers")));
        goods.setOrigin(cleanFieldValue(getCsvValue(record, "Manufactured In")));
        goods.setPointSale(cleanFieldValue(getCsvValue(record, "Sold At")));
    }

    /**
     * 设置风险相关字段 - CSV版本
     */
    private void setRiskCsvFields(UsUnqualifiedGoods goods, CSVRecord record) {
        goods.setDangerDescription(cleanFieldValue(getCsvValue(record, "Hazard Description")));
        goods.setAccidentDescription(cleanFieldValue(getCsvValue(record, "Incidents")));

        // 商品描述也作为风险信息的一部分
        String description = cleanFieldValue(getCsvValue(record, "Description"));
        if (description != null && !description.isEmpty()) {
            goods.setRecallCause(description);
        }
    }

    /**
     * 设置召回相关信息 - CSV版本
     */
    private void setRecallCsvFields(UsUnqualifiedGoods goods, CSVRecord record) {
        goods.setRemedyDescription(cleanFieldValue(getCsvValue(record, "Remedy")));
        goods.setRecallAmount(cleanFieldValue(getCsvValue(record, "Units")));

        // 如果召回原因为空，使用危险描述作为召回原因
        if (goods.getRecallCause() == null || goods.getRecallCause().isEmpty()) {
            goods.setRecallCause(cleanFieldValue(getCsvValue(record, "Hazard Description")));
        }

        // 设置召回时间 - 只从 Date 字段获取
        Date recallDate = extractRecallDateFromCsv(record);
        goods.setRecallTime(recallDate);
    }

    /**
     * 设置其他字段 - CSV版本
     */
    private void setOtherCsvFields(UsUnqualifiedGoods goods, CSVRecord record, String csvFilePath) {
        // 设置爬取时间和状态
        goods.setSpiderTime(new Date());
        goods.setStatus(0L);

        // 设置创建信息
        goods.setCreateUser("system");
        goods.setCreateDept("system");
        goods.setIsDeleted(0L);

        // 设置备注信息
        String remark = buildRemarkFromCsv(record);
        goods.setRemark(remark);
    }

    /**
     * 构建备注信息 - CSV版本
     */
    private String buildRemarkFromCsv(CSVRecord record) {
        StringBuilder remark = new StringBuilder();

        // 添加召回编号
        String recallNumber = getCsvValue(record, "Recall Number");
        if (recallNumber != null && !recallNumber.trim().isEmpty()) {
            remark.append("召回编号: ").append(recallNumber.trim());
        }

        // 添加产品名称
        String productName = getCsvValue(record, "Name of product");
        if (productName != null && !productName.trim().isEmpty()) {
            if (remark.length() > 0) remark.append(" | ");
            remark.append("产品名称: ").append(productName.trim());
        }

        // 添加补救类型
        String remedyType = getCsvValue(record, "Remedy Type");
        if (remedyType != null && !remedyType.trim().isEmpty()) {
            if (remark.length() > 0) remark.append(" | ");
            remark.append("补救类型: ").append(remedyType.trim());
        }

        // 添加销售渠道
        String soldAtLabel = getCsvValue(record, "Sold At Label");
        if (soldAtLabel != null && !soldAtLabel.trim().isEmpty()) {
            if (remark.length() > 0) remark.append(" | ");
            remark.append("销售渠道: ").append(soldAtLabel.trim());
        }

        return remark.length() > 0 ? remark.toString() : "来自CPSC召回数据";
    }

    /**
     * 获取CSV字段值，处理可能的空值
     */
    private String getCsvValue(CSVRecord record, String columnName) {
        try {
            // 尝试直接获取
            String value = record.get(columnName);
            if (value != null) {
                return value.trim();
            }

            // 如果直接获取失败，尝试忽略大小写和空格
            Map<String, Integer> headerMap = record.getParser().getHeaderMap();
            for (String header : headerMap.keySet()) {
                if (header.trim().equalsIgnoreCase(columnName.trim())) {
                    value = record.get(header);
                    return value != null ? value.trim() : null;
                }
            }

            System.out.println("  列 '" + columnName + "' 不存在，可用列: " + headerMap.keySet());
            return null;

        } catch (IllegalArgumentException e) {
            System.out.println("  列 '" + columnName + "' 不存在于记录中");
            return null;
        } catch (Exception e) {
            System.err.println("获取CSV字段值失败 [" + columnName + "]: " + e.getMessage());
            return null;
        }
    }

    /**
     * 清理字段值
     */
    private String cleanFieldValue(String value) {
        if (value == null) {
            return null;
        }
        String cleaned = value.trim();

        // 清理HTML实体和特殊字符
        cleaned = cleaned.replace("&nbsp;", " ")
                .replace("&amp;", "&")
                .replace("&lt;", "<")
                .replace("&gt;", ">")
                .replace("&quot;", "\"")
                .replace("&#39;", "'");

        return cleaned.isEmpty() ? null : cleaned;
    }

    /**
     * 翻译商品字段
     */
    private void translateGoodsFields(UsUnqualifiedGoods goods) {
        UsUnqualifiedGoodsZh en = new UsUnqualifiedGoodsZh();
        BeanUtils.copyProperties(goods, en);
        en.setBusinessId(goods.getId());
        try {
            //召回数量
            if (goods.getRecallAmount() != null && !goods.getRecallAmount().trim().isEmpty()) {
                String translatedName = baiduTranslationService.translateWithCache(
                        goods.getRecallAmount(), "en", "zh");
                en.setRecallAmount(translatedName); // 需要实体类有此字段
            }

            // 翻译售出地点
            if (goods.getPointSale() != null && !goods.getPointSale().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getPointSale(), "en", "zh");
                en.setPointSale(translatedDanger);
            }

            //产地
            if (goods.getProducers() != null && !goods.getProducers().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getProducers(), "en", "zh");
                en.setProducers(translatedDanger);
            }

            //制造商
            if (goods.getOrigin() != null && !goods.getOrigin().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getOrigin(), "en", "zh");
                en.setOrigin(translatedDanger);
            }

            //事故/伤亡描述
            if (goods.getAccidentDescription() != null && !goods.getAccidentDescription().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getAccidentDescription(), "en", "zh");
                en.setAccidentDescription(translatedDanger);
            }

            // 翻译召回原因
            if (goods.getRecallCause() != null && !goods.getRecallCause().trim().isEmpty()) {
                String translatedCause = baiduTranslationService.translateWithCache(
                        goods.getRecallCause(), "en", "zh");
                en.setRecallCause(translatedCause);
            }

            // 翻译补救描述
            if (goods.getRemedyDescription() != null && !goods.getRemedyDescription().trim().isEmpty()) {
                String translatedRemedy = baiduTranslationService.translateWithCache(
                        goods.getRemedyDescription(), "en", "zh");
                en.setRemedyDescription(translatedRemedy);
            }

            // 设置翻译状态
            en.setTranslated("0");
        } catch (Exception e) {
            System.err.println("翻译商品字段失败，但继续保存原文: " + e.getMessage());
            en.setTranslated("1");
            // 即使翻译失败，也继续保存原文
        } finally {
            en.setTranslatedTime(new Date());
            usUnqualifiedGoodsZhMapper.insertUsUnqualifiedGoodsZh(en);
        }

    }

    /**
     * 打印处理结果
     */
    private void printProcessResult(int totalRecords) {
        System.out.println("\n==================== CSV处理结果 ====================");
        System.out.println("总记录数: " + totalRecords);
        System.out.println("成功保存: " + successCount + " 条");
        System.out.println("失败保存: " + failureCount + " 条");
        System.out.println("跳过记录: " + skippedCount + " 条");
        System.out.println("  - 因商品名称为空跳过: " + emptyNameCount + " 条");
        System.out.println("  - 因召回时间为空跳过: " + emptyRecallTimeCount + " 条");
        System.out.println("  - 因时间条件跳过: " + timeConditionSkippedCount + " 条");
        System.out.println("====================================================");
    }
}