package com.cn.fdapfe.biz.service.impl;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cn.fdapfe.biz.domain.Formulas;
import com.cn.fdapfe.biz.mapper.FormulasMapper;
import com.cn.fdapfe.common.utils.DateUtils;
import com.cn.fdapfe.common.utils.SecurityUtils;
import com.cn.fdapfe.common.utils.StringUtils;
import com.cn.fdapfe.common.utils.http.HttpUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cn.fdapfe.biz.mapper.FdAlgorithmMapper;
import com.cn.fdapfe.biz.domain.FdAlgorithm;
import com.cn.fdapfe.biz.service.IFdAlgorithmService;

import javax.annotation.Resource;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
 * 故障诊断算法功能验证Service业务层处理
 * 
 * @author Allen
 * @date 2025-03-07
 */
@Service
public class FdAlgorithmServiceImpl implements IFdAlgorithmService

{
    private static final Logger logger = LoggerFactory.getLogger(FdAlgorithmServiceImpl.class);
    @Resource
    private FdAlgorithmMapper mapper;
    private static final long CHECK_INTERVAL = 1000; // 检查间隔1秒（毫秒）
    @Resource
    private FormulasMapper formulasMapper;

    /**
     * 查询故障诊断算法功能验证
     * 
     * @param id 故障诊断算法功能验证主键
     * @return 故障诊断算法功能验证
     */
    @Override
    public FdAlgorithm selectFdAlgorithmById(String id)
    {
        return mapper.selectById(id);
    }

    /**
     * 查询故障诊断算法功能验证列表
     * 
     * @param po 故障诊断算法功能验证
     * @return 故障诊断算法功能验证
     */
    @Override
    public List<FdAlgorithm> selectFdAlgorithmList(FdAlgorithm po)
    {
        QueryWrapper<FdAlgorithm> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(po.getId()),"id",po.getId())
                .like(StringUtils.isNotEmpty(po.getName()),"name",po.getName())
                .like(StringUtils.isNotEmpty(po.getDataId()),"model_id",po.getDataId())
                .eq(StringUtils.isNotEmpty(po.getDataId()),"data_id",po.getDataId());
        if(po.getStartTime()!=null){
            wrapper.ge("start_time",po.getStartTime());
        }
        if(po.getEndTime()!=null){
            wrapper.le("end_time",po.getEndTime());
        }

        return mapper.selectList(wrapper);
    }

    /**
     * 新增故障诊断算法功能验证
     * 
     * @param po 故障诊断算法功能验证
     * @return 结果
     */
    @Override
    public int insertFdAlgorithm(FdAlgorithm po) throws IOException, InterruptedException {
        po.setCreateTime(DateUtils.getNowDate());
        po.setCreateBy(SecurityUtils.getUsername());

        // 记录开始执行外部程序的时间
        Date startTime = new Date();
        po.setStartTime(startTime);

        // 启动外部程序
        ExeProcessManager.ExeResult topOneResult = ExeProcessManager.startExe(
                po.getOutputPath() + File.separator + "topOne.exe",
                false
        );
        ExeProcessManager.ExeResult topTwoResult = ExeProcessManager.startExe(
                po.getOutputPath() + File.separator + "topTwo.exe",
                false
        );
        // 记录执行结束时间（两个进程都已执行完毕）
        Date endTime = new Date();
        po.setEndTime(endTime);

        // 循环获取并解析输出文件（保留原有逻辑）
        Object json = checkAndParseJson(po.getOutputPath() + File.separator + "output", "return_indicators.json");
        System.err.println(json);
        po.setReturnData(json.toString());

        return mapper.insert(po);
    }

    /**
     * 因为文件生成有一定延迟，循环获取生成的文件
     * @param directoryPath
     * @param fileName
     * @return
     */
    public static Object checkAndParseJson(String directoryPath, String fileName) {
        File directory = new File(directoryPath);
        if (!directory.exists() || !directory.isDirectory()) {
            System.err.println("错误：指定目录不存在或不是有效目录 - " + directoryPath);
            return null;
        }

        File jsonFile = new File(directory, fileName);
        while (!jsonFile.exists()) {
            System.out.println("等待文件出现：" + fileName);
            try {
                Thread.sleep(CHECK_INTERVAL);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("检查过程被中断");
                return null;
            }
            jsonFile = new File(directory, fileName); // 重新获取文件对象（防止目录变化）
        }

        System.out.println("找到文件：" + jsonFile.getAbsolutePath());
        try {
            return new ObjectMapper().readValue(jsonFile, Object.class);
        } catch (IOException e) {
            System.err.println("解析错误：" + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 修改故障诊断算法功能验证
     * 
     * @param po 故障诊断算法功能验证
     * @return 结果
     */
    @Override
    public int updateFdAlgorithm(FdAlgorithm po) throws IOException, InterruptedException {
        FdAlgorithm id = mapper.selectById(po.getId());
        po.setUpdateTime(DateUtils.getNowDate());
        po.setUpdateBy(SecurityUtils.getUsername());
        return id == null? insertFdAlgorithm(po): mapper.updateById(po);
    }

    /**
     * 批量删除故障诊断算法功能验证
     * 
     * @param ids 需要删除的故障诊断算法功能验证主键
     * @return 结果
     */
    @Override
    public int deleteFdAlgorithmByIds(String[] ids)
    {
        return ids.length == 1? mapper.deleteById(ids[0]):mapper.deleteBatchIds(Arrays.asList(ids));
    }
    public static JSONArray convertToStandardJson(String input) {
        // 匹配键值对
        Pattern pattern = Pattern.compile("(\\w+)=([^,}]+)");
        Matcher matcher = pattern.matcher(input);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "\"" + matcher.group(1) + "\":" + matcher.group(2));
        }
        matcher.appendTail(sb);
        String standardJson = sb.toString();
        return JSON.parseArray(standardJson);
    }
    @Override
    public Map<String, List<Object>> handleVerify(FdAlgorithm po) throws IOException, InterruptedException {
        List<String> verifyData = po.getVerifyData();
        String returnData = po.getReturnData();
        JSONArray dataArray = convertToStandardJson(returnData);

        // 创建 JavaScript 脚本引擎
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        Map<String, List<Object>> resultMap = new HashMap<>();

        for (String formulaId : verifyData) {
            QueryWrapper<Formulas> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Formulas::getFormulaId, formulaId);
            Formulas one = formulasMapper.selectOne(wrapper);
            if (one != null) {
                String originalFormula = one.getOriginalFormula();
                String formulaName = one.getFormulaName();

                // 初始化该公式的结果列表
                List<Object> results = resultMap.computeIfAbsent(formulaName, k -> new ArrayList<>());

                // 遍历 returnData 中的每个对象
                for (int i = 0; i < dataArray.size(); i++) {
                    JSONObject dataObject = dataArray.getJSONObject(i);
                    // 将对象中的参数值放入脚本引擎
                    for (Map.Entry<String, Object> entry : dataObject.entrySet()) {
                        engine.put(entry.getKey(), entry.getValue());
                    }
                    try {
                        // 执行公式计算
                        Object result = engine.eval(originalFormula);
                        if (result instanceof Number) {
                            // 使用 DecimalFormat 保留两位小数
                            DecimalFormat df = new DecimalFormat("#.00");
                            String formattedResult = df.format(result);
                            results.add(formattedResult);
                        } else {
                            results.add(result);
                        }
                    } catch (ScriptException e) {
                        System.err.println("公式计算出错: " + e.getMessage());
                    }
                }
            }
        }
        System.err.println("公式计算结果: " + resultMap);
        return resultMap;
    }
    @Override
    public List<Map<String, Object>> getOptions() {
        return mapper.getOptions();
    }
}
