package com.spider.quartz.task;

import com.spider.quartz.config.BaiduAiTranslationService;
import com.spider.quartz.domain.EuUnqualifiedGoods;
import com.spider.quartz.domain.EuUnqualifiedGoodsZh;
import com.spider.quartz.domain.UsUnqualifiedGoods;
import com.spider.quartz.domain.UsUnqualifiedGoodsZh;
import com.spider.quartz.mapper.EuUnqualifiedGoodsMapper;
import com.spider.quartz.mapper.EuUnqualifiedGoodsZhMapper;
import com.spider.quartz.mapper.UsUnqualifiedGoodsZhMapper;
import com.spider.quartz.util.SpiderXmlUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 欧盟XML数据处理器 - 专门负责XML解析和数据保存
 * 优化：基于召回时间的增量导入
 */
@Component
public class EuropeXmlProcessor {

    @Autowired
    private EuUnqualifiedGoodsMapper euUnqualifiedGoodsMapper;
    @Autowired
    private EuUnqualifiedGoodsZhMapper euUnqualifiedGoodsZhMapper;

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


    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private int successCount = 0;
    private int failureCount = 0;
    private int skippedCount = 0;
    private int emptyNameCount = 0;
    private int emptyRecallTimeCount = 0;
    /**
     * 处理XML文件 - 主入口方法
     */
    public void processXmlFile(File xmlFile) {
        try {
            System.out.println("开始处理XML文件: " + xmlFile.getAbsolutePath());

            // 1. 预处理XML文件
            File cleanedXmlFile = SpiderXmlUtil.preprocessXmlFile(xmlFile);
            if (cleanedXmlFile == null) {
                System.err.println("XML文件预处理失败");
                return;
            }

            // 2. 解析XML文件
            List<Element> notificationElements = parseXmlFile(cleanedXmlFile);
            if (notificationElements.isEmpty()) {
                System.err.println("XML文件解析结果为空");
                return;
            }

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

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

            // 4. 处理每条记录
            processNotificationElements(notificationElements, xmlFile.getAbsolutePath(), latestRecallTime);

            // 5. 输出处理结果
            printProcessResult(notificationElements.size());

            // 6. 清理临时文件
            if (!cleanedXmlFile.equals(xmlFile)) {
                cleanedXmlFile.delete();
            }

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

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

    /**
     * 解析XML文件
     */
    private List<Element> parseXmlFile(File xmlFile) {
        List<Element> notifications = new ArrayList<>();
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

            // 防止XXE攻击的安全配置
            factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
            factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
            factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
            factory.setXIncludeAware(false);
            factory.setExpandEntityReferences(false);

            DocumentBuilder builder = factory.newDocumentBuilder();

            // 设置错误处理器
            builder.setErrorHandler(new org.xml.sax.ErrorHandler() {
                @Override
                public void warning(org.xml.sax.SAXParseException exception) {
                    System.err.println("XML解析警告: " + exception.getMessage());
                }

                @Override
                public void error(org.xml.sax.SAXParseException exception) {
                    System.err.println("XML解析错误: " + exception.getMessage());
                }

                @Override
                public void fatalError(org.xml.sax.SAXParseException exception) {
                    System.err.println("XML解析致命错误: " + exception.getMessage());
                }
            });

            Document document = builder.parse(xmlFile);

            NodeList nodeList = document.getElementsByTagName("notifications");
            for (int i = 0; i < nodeList.getLength(); i++) {
                notifications.add((Element) nodeList.item(i));
            }

            System.out.println("成功解析 " + notifications.size() + " 个通知记录");

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

    /**
     * 处理通知元素列表 - 基于召回时间的增量导入
     */
    private void processNotificationElements(List<Element> notificationElements, String xmlFilePath, Date latestRecallTime) {
        int processedCount = 0;
        boolean hasExistingData = (latestRecallTime != null);

        System.out.println("开始处理通知元素，现有数据: " + (hasExistingData ? "是" : "否"));

        for (int i = 0; i < notificationElements.size(); i++) {
            Element notificationElement = notificationElements.get(i);
            try {
                String caseNumber = SpiderXmlUtil.getElementText(notificationElement, "caseNumber");
                System.out.println("处理记录 " + (i + 1) + "/" + notificationElements.size() + " - 案例编号: " + caseNumber);

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

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

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

    /**
     * 检查是否应该处理记录 - 基于召回时间的增量导入逻辑
     */
    private boolean shouldProcessRecord(Element notificationElement, Date latestRecallTime, boolean hasExistingData) {
        try {
            // 1. 检查商品名称是否为空
            String goodsName = getGoodsNameWithFallback(notificationElement);
            if (goodsName == null || goodsName.trim().isEmpty()) {
                System.out.println("  跳过: 商品名称为空");
                emptyNameCount++;
                return false;
            }

            // 2. 提取召回日期
            Date recallDate = extractRecallDateFromMeasures(notificationElement);

            // 3. 检查召回日期是否为空
            if (recallDate == null) {
                System.out.println("  跳过: 无召回日期");
                emptyRecallTimeCount++;
                return false;
            }
            // 如果数据库中没有数据，处理所有记录（全量导入）
            if (!hasExistingData) {
                System.out.println("  全量模式: 处理所有记录");
                return true;
            }

            // 如果记录没有召回日期，跳过（无法比较时间）
            if (recallDate == null) {
                System.out.println("  跳过: 无召回日期");
                return false;
            }

            // 增量导入：只处理召回时间大于最新时间的记录
            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));
            }

            return shouldProcess;

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

    /**
     * 从measures中提取召回日期
     */
    private Date extractRecallDateFromMeasures(Element notificationElement) {
        try {
            String measuresText = SpiderXmlUtil.getElementText(notificationElement, "measures");
            if (measuresText == null || measuresText.isEmpty()) {
                return null;
            }

            // 使用正则表达式提取日期 - 格式: dd/MM/yyyy
            Date recallDate = SpiderXmlUtil.extractDateFromText(measuresText,
                    "Date of entry into force:\\s*([0-9]{1,2}/[0-9]{1,2}/[0-9]{4})",
                    "dd/MM/yyyy");

            if (recallDate != null) {
                System.out.println("  提取到召回日期: " + DATE_FORMAT.format(recallDate));
            } else {
                System.out.println("  未提取到召回日期");
            }

            return recallDate;

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

    /**
     * 保存XML数据到数据库
     */
    private boolean saveXmlDataToDatabase(Element notificationElement, String xmlFilePath) {
        try {
            EuUnqualifiedGoods goods = new EuUnqualifiedGoods();

            // 1. 设置基础字段 - 优化商品名称获取
            setBasicFields(goods, notificationElement);

            // 验证必要字段
            if (goods.getGoodsName() == null || goods.getGoodsName().trim().isEmpty()) {
                System.err.println("商品名称为空，跳过此记录");
                return false;
            }

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

            // 3. 设置整改措施和召回日期
            setRemedyAndRecallFields(goods, notificationElement);

            // 4. 设置其他字段
            setOtherFields(goods, notificationElement, xmlFilePath);

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

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

    /**
     * 翻译商品字段
     */
    private void translateGoodsFields(EuUnqualifiedGoods goods) {
        EuUnqualifiedGoodsZh en = new EuUnqualifiedGoodsZh();
        BeanUtils.copyProperties(goods, en);
        en.setBusinessId(goods.getId());
        try {
            //商品名称
            if (goods.getGoodsName() != null && !goods.getGoodsName().trim().isEmpty()) {
                String translatedName = baiduTranslationService.translateWithCache(
                        goods.getGoodsName(), "en", "zh");
                en.setGoodsName(translatedName); // 需要实体类有此字段
            }
            //品牌
            if (goods.getBrand() != null && !goods.getBrand().trim().isEmpty()) {
                String translatedName = baiduTranslationService.translateWithCache(
                        goods.getBrand(), "en", "zh");
                en.setBrand(translatedName); // 需要实体类有此字段
            }

            //通知国家
            if (goods.getNoticeCountry() != null && !goods.getNoticeCountry().trim().isEmpty()) {
                String translatedName = baiduTranslationService.translateWithCache(
                        goods.getNoticeCountry(), "en", "zh");
                en.setNoticeCountry(translatedName); // 需要实体类有此字段
            }

            // 产品类别
            if (goods.getGoodsCategory() != null && !goods.getGoodsCategory().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getGoodsCategory(), "en", "zh");
                en.setGoodsCategory(translatedDanger);
            }

            //产品种类
            if (goods.getGoodsKinds() != null && !goods.getGoodsKinds().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getGoodsKinds(), "en", "zh");
                en.setGoodsKinds(translatedDanger);
            }

            //原产国
            if (goods.getOriginCountry() != null && !goods.getOriginCountry().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getOriginCountry(), "en", "zh");
                en.setOriginCountry(translatedDanger);
            }

            //风险类型
            if (goods.getRiskType() != null && !goods.getRiskType().trim().isEmpty()) {
                String translatedDanger = baiduTranslationService.translateWithCache(
                        goods.getRiskType(), "en", "zh");
                en.setRiskType(translatedDanger);
            }

            // 风险描述
            if (goods.getRiskDescription() != null && !goods.getRiskDescription().trim().isEmpty()) {
                String translatedCause = baiduTranslationService.translateWithCache(
                        goods.getRiskDescription(), "en", "zh");
                en.setRiskDescription(translatedCause);
            }

            // 不合格原因
            if (goods.getUnqualifiedCause() != null && !goods.getUnqualifiedCause().trim().isEmpty()) {
                String translatedRemedy = baiduTranslationService.translateWithCache(
                        goods.getUnqualifiedCause(), "en", "zh");
                en.setUnqualifiedCause(translatedRemedy);
            }

            //补救措施
            if (goods.getRemedyMeasures() != null && !goods.getRemedyMeasures().trim().isEmpty()) {
                String translatedRemedy = baiduTranslationService.translateWithCache(
                        goods.getRemedyMeasures(), "en", "zh");
                en.setRemedyMeasures(translatedRemedy);
            }

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

    }

    /**
     * 设置基础字段 - 优化版本：当name为空时使用product字段
     */
    private void setBasicFields(EuUnqualifiedGoods goods, Element element) {
        // 优化商品名称获取逻辑
        String goodsName = getGoodsNameWithFallback(element);
        goods.setGoodsName(goodsName);

        goods.setNoticeCountry(SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "notifyingCountry")));
        goods.setGoodsCategory(SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "category")));
        goods.setGoodsKinds(SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "product")));
        goods.setBrand(SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "brand")));
        goods.setOriginCountry(SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "countryOfOrigin")));
        goods.setRiskType(SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "riskType")));
    }

    /**
     * 获取商品名称 - 当name为空时使用product字段作为备选
     */
    private String getGoodsNameWithFallback(Element element) {
        // 1. 首先尝试获取name字段
        String name = SpiderXmlUtil.getElementText(element, "name");
        return SpiderXmlUtil.cleanFieldValue(name);
    }

    /**
     * 设置风险相关字段
     */
    private void setRiskFields(EuUnqualifiedGoods goods, Element element) {
        String dangerText = SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "danger"));
        Map<String, String> riskInfo = SpiderXmlUtil.splitRiskAndCause(dangerText);
        goods.setRiskDescription(riskInfo.get("riskDescription"));
        goods.setUnqualifiedCause(riskInfo.get("unqualifiedCause"));
    }

    /**
     * 设置整改措施和召回日期
     */
    private void setRemedyAndRecallFields(EuUnqualifiedGoods goods, Element element) {
        String measuresText = SpiderXmlUtil.cleanFieldValue(SpiderXmlUtil.getElementText(element, "measures"));
        goods.setRemedyMeasures(measuresText);

        // 提取召回日期 - 若获取时间失败，则存空
        Date recallDate = extractRecallDateFromMeasures(element);
        goods.setRecallTime(recallDate); // 可能为null
    }

    /**
     * 设置其他字段
     */
    private void setOtherFields(EuUnqualifiedGoods goods, Element element, String xmlFilePath) {
        // 设置爬取时间和状态
        goods.setSpiderTime(new Date());
        goods.setStatus(0L);

        // 设置备注信息
        Date recallDate = extractRecallDateFromMeasures(element);
        String remark = buildRemarkFromXml(element, recallDate != null);
        goods.setRemark(remark);
    }

    /**
     * 构建备注信息
     */
    private String buildRemarkFromXml(Element element, boolean hasRecallDate) {
        StringBuilder remark = new StringBuilder();

        // 案例编号
        String caseNumber = SpiderXmlUtil.getElementText(element, "caseNumber");
        if (caseNumber != null && !caseNumber.isEmpty()) {
            remark.append("案例编号: ").append(caseNumber);
        }

        // 公司召回代码
        String recallCode = SpiderXmlUtil.getElementText(element, "companyRecallCode");
        if (recallCode != null && !recallCode.trim().isEmpty()) {
            if (remark.length() > 0) remark.append(" | ");
            remark.append("召回代码: ").append(recallCode.trim());
        }

        // 风险等级
        String riskLevel = SpiderXmlUtil.getElementText(element, "level");
        if (riskLevel != null && !riskLevel.isEmpty()) {
            if (remark.length() > 0) remark.append(" | ");
            remark.append("风险等级: ").append(riskLevel);
        }

        // 生产日期
        String productionDates = SpiderXmlUtil.getElementText(element, "productionDates");
        if (productionDates != null && !productionDates.isEmpty()) {
            if (remark.length() > 0) remark.append(" | ");
            remark.append("生产日期: ").append(productionDates);
        }

        return remark.toString();
    }

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