package org.hzhub.erp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.hzhub.erp.common.page.TableDataInfo;
import org.hzhub.erp.domain.entity.ErpApiConfig;
import org.hzhub.erp.domain.entity.ErpApiParam;
import org.hzhub.erp.domain.vo.ApiExecutionResult;
import org.hzhub.erp.domain.vo.ApiTestResultVO;
import org.hzhub.erp.domain.vo.ErpApiConfigVO;
import org.hzhub.erp.mapper.ErpApiConfigMapper;
import org.hzhub.erp.mapper.ErpApiParamMapper;
import org.hzhub.erp.service.IErpApiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * ERP动态API配置Service实现
 * 使用MySQL数据源存储配置信息
 *
 * @author HZHub Team
 */
@Service
@DS("master")  // 使用MySQL数据源（master）
@RequiredArgsConstructor
public class ErpApiServiceImpl implements IErpApiService {

    private static final Logger log = LoggerFactory.getLogger(ErpApiServiceImpl.class);

    private final ErpApiConfigMapper apiConfigMapper;
    private final ErpApiParamMapper apiParamMapper;
    private final DynamicApiExecutor dynamicApiExecutor;
    private final JdbcTemplate jdbcTemplate;
    private final ApiStatsRecorder apiStatsRecorder;

    @Override
    public TableDataInfo<ErpApiConfigVO> queryApiConfigList(ErpApiConfigVO query, Integer pageNum, Integer pageSize) {
        Page<ErpApiConfig> page = new Page<>(pageNum, pageSize);

        LambdaQueryWrapper<ErpApiConfig> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(query.getApiName())) {
            wrapper.like(ErpApiConfig::getApiName, query.getApiName());
        }
        if (StrUtil.isNotBlank(query.getApiPath())) {
            wrapper.like(ErpApiConfig::getApiPath, query.getApiPath());
        }
        if (query.getStatus() != null) {
            wrapper.eq(ErpApiConfig::getStatus, query.getStatus());
        }
        wrapper.orderByDesc(ErpApiConfig::getCreateTime);

        IPage<ErpApiConfig> configPage = apiConfigMapper.selectPage(page, wrapper);

        // 转换为VO
        List<ErpApiConfigVO> voList = configPage.getRecords().stream()
            .map(config -> BeanUtil.copyProperties(config, ErpApiConfigVO.class))
            .collect(Collectors.toList());

        return new TableDataInfo<>(voList, configPage.getTotal());
    }

    @Override
    public ErpApiConfig selectApiConfigById(Long apiId) {
        return apiConfigMapper.selectById(apiId);
    }

    @Override
    public List<ErpApiParam> selectApiParamsByApiId(Long apiId) {
        return apiParamMapper.selectByApiId(apiId);
    }

    @Override
    public ErpApiConfig selectApiConfigByPath(String apiPath, String apiMethod, String apiVersion) {
        return apiConfigMapper.selectByPathAndMethod(apiPath, apiMethod, apiVersion);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertApiConfig(ErpApiConfig config) {
        return apiConfigMapper.insert(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateApiConfig(ErpApiConfig config) {
        return apiConfigMapper.updateById(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteApiConfigByIds(Long[] apiIds) {
        int count = 0;
        for (Long apiId : apiIds) {
            count += apiConfigMapper.deleteById(apiId);
        }
        return count;
    }

    @Override
    public int updateApiStatus(ErpApiConfig config) {
        ErpApiConfig updateConfig = new ErpApiConfig();
        updateConfig.setApiId(config.getApiId());
        updateConfig.setStatus(config.getStatus());
        return apiConfigMapper.updateById(updateConfig);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importFromTable(String[] tableNames, String dataSource) {
        // TODO: 实现从表导入功能（Phase 2）
        log.info("从表导入功能待实现: tableNames={}, dataSource={}", Arrays.toString(tableNames), dataSource);
    }

    @Override
    public void syncTableStructure(Long apiId) {
        // TODO: 实现同步表结构功能（Phase 4）
        log.info("同步表结构功能待实现: apiId={}", apiId);
    }

    @Override
    public ApiTestResultVO testApi(Long apiId, Map<String, Object> testParams, String clientIp, String userId) {
        ErpApiConfig config = selectApiConfigById(apiId);
        if (config == null) {
            throw new RuntimeException("API配置不存在");
        }

        ApiTestResultVO result = new ApiTestResultVO();
        result.setApiPath(config.getApiPath());
        result.setTestMethod(config.getApiMethod());
        result.setRequestParams(testParams);

        long startTime = System.currentTimeMillis();

        try {
            ApiExecutionResult executionResult = dynamicApiExecutor.execute(config, testParams);
            Object data = executionResult.getData();
            String executedSql = executionResult.getExecutedSql();
            long executionTime = System.currentTimeMillis() - startTime;

            result.setSuccess(true);
            result.setData(data);
            result.setExecutionTime(executionTime);
            result.setExecutedSql(executedSql);

            log.info("API测试成功: apiId={}, executionTime={}ms", apiId, executionTime);

            // 记录成功统计（异步记录，不影响响应）
            try {
                String callParamsJson = testParams.toString();
                apiStatsRecorder.recordSuccess(apiId, callParamsJson, executedSql,
                                               executionTime, clientIp, userId);
            } catch (Exception statsError) {
                log.warn("统计记录失败（不影响API响应）: {}", statsError.getMessage());
            }

        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());

            // 获取错误堆栈
            StringBuilder stackTrace = new StringBuilder();
            for (StackTraceElement element : e.getStackTrace()) {
                stackTrace.append(element.toString()).append("\n");
            }
            result.setErrorStack(stackTrace.toString());

            log.error("API测试失败: apiId={}, error={}", apiId, e.getMessage(), e);

            // 记录错误统计
            long executionTime = System.currentTimeMillis() - startTime;
            String executedSql = config.getSqlTemplate();
            try {
                String callParamsJson = testParams.toString();
                apiStatsRecorder.recordError(apiId, callParamsJson, executedSql,
                                             executionTime, e.getMessage(),
                                             stackTrace.toString(), clientIp, userId);
            } catch (Exception statsError) {
                log.warn("统计记录失败（不影响API响应）: {}", statsError.getMessage());
            }
        }

        return result;
    }

    @Override
    public Map<String, String> generateApiDoc(Long apiId) {
        // TODO: 实现API文档生成（Phase 3）
        ErpApiConfig config = selectApiConfigById(apiId);
        List<ErpApiParam> params = selectApiParamsByApiId(apiId);

        Map<String, String> docMap = new HashMap<>();
        docMap.put("basic", generateBasicInfo(config));
        docMap.put("params", generateParamsInfo(params));
        docMap.put("sql", config.getSqlTemplate());

        return docMap;
    }

    @Override
    public Map<String, Object> getApiStats(Long apiId, String startTime, String endTime) {
        // 查询统计数据
        Map<String, Object> stats = new HashMap<>();

        try {
            // 构建SQL查询
            StringBuilder sql = new StringBuilder();
            sql.append("SELECT ");
            sql.append("COUNT(*) AS totalCalls, ");
            sql.append("SUM(CASE WHEN call_status = 'SUCCESS' THEN 1 ELSE 0 END) AS successCalls, ");
            sql.append("SUM(CASE WHEN call_status = 'ERROR' THEN 1 ELSE 0 END) AS errorCalls, ");
            sql.append("AVG(response_time) AS avgResponseTime, ");
            sql.append("MAX(response_time) AS maxResponseTime, ");
            sql.append("MIN(response_time) AS minResponseTime ");
            sql.append("FROM erp_api_stats ");
            sql.append("WHERE api_id = ? ");

            List<Object> params = new ArrayList<>();
            params.add(apiId);

            if (startTime != null && !startTime.isEmpty()) {
                sql.append("AND call_time >= ? ");
                params.add(startTime);
            }

            if (endTime != null && !endTime.isEmpty()) {
                sql.append("AND call_time <= ? ");
                params.add(endTime);
            }

            log.info("查询统计数据: apiId={}, SQL={}, params={}", apiId, sql.toString(), params);

            // 执行查询
            Map<String, Object> result = jdbcTemplate.queryForMap(sql.toString(), params.toArray());

            log.info("查询结果: {}", result);

            // 处理类型转换（MySQL返回类型可能不同）
            // COUNT返回Long或BigDecimal
            Object totalCallsObj = result.get("totalCalls");
            stats.put("totalCalls", convertToLong(totalCallsObj));

            Object successCallsObj = result.get("successCalls");
            stats.put("successCalls", convertToLong(successCallsObj));

            Object errorCallsObj = result.get("errorCalls");
            stats.put("errorCalls", convertToLong(errorCallsObj));

            // 响应时间处理（可能为null）
            Object avgTime = result.get("avgResponseTime");
            stats.put("avgResponseTime", avgTime != null ? convertToLong(avgTime) : 0);

            Object maxTime = result.get("maxResponseTime");
            stats.put("maxResponseTime", maxTime != null ? convertToLong(maxTime) : 0);

            Object minTime = result.get("minResponseTime");
            stats.put("minResponseTime", minTime != null ? convertToLong(minTime) : 0);

            // 计算错误率
            Long totalCalls = (Long) stats.get("totalCalls");
            Long errorCalls = (Long) stats.get("errorCalls");
            Double errorRate = totalCalls > 0 ? (errorCalls * 100.0 / totalCalls) : 0.0;
            stats.put("errorRate", errorRate);

            log.info("统计数据返回: totalCalls={}, successCalls={}, errorCalls={}, avgTime={}ms",
                    totalCalls, stats.get("successCalls"), errorCalls, stats.get("avgResponseTime"));

        } catch (Exception e) {
            log.error("查询统计数据失败: apiId={}, error={}", apiId, e.getMessage(), e);
            // 返回默认值
            stats.put("totalCalls", 0);
            stats.put("successCalls", 0);
            stats.put("errorCalls", 0);
            stats.put("avgResponseTime", 0);
            stats.put("maxResponseTime", 0);
            stats.put("minResponseTime", 0);
            stats.put("errorRate", 0.0);
        }

        return stats;
    }

    /**
     * 将数据库返回的数值转换为Long
     * MySQL可能返回Long、BigDecimal或Integer
     */
    private Long convertToLong(Object value) {
        if (value == null) {
            return 0L;
        }

        if (value instanceof Long) {
            return (Long) value;
        } else if (value instanceof java.math.BigDecimal) {
            return ((java.math.BigDecimal) value).longValue();
        } else if (value instanceof Integer) {
            return ((Integer) value).longValue();
        } else if (value instanceof Number) {
            return ((Number) value).longValue();
        } else {
            log.warn("无法转换类型: {} -> {}", value.getClass().getName(), value);
            return 0L;
        }
    }

    @Override
    public List<Map<String, Object>> getApiErrorLog(Long apiId, Integer limit) {
        // 查询错误日志
        try {
            String sql = "SELECT stats_id, api_id, call_time, call_params, response_time, " +
                        "call_status, error_message, error_stack, client_ip, user_id " +
                        "FROM erp_api_stats " +
                        "WHERE api_id = ? AND call_status = 'ERROR' " +
                        "ORDER BY call_time DESC " +
                        "LIMIT ?";

            List<Map<String, Object>> logs = jdbcTemplate.queryForList(sql, apiId, limit != null ? limit : 10);
            return logs;

        } catch (Exception e) {
            log.error("查询错误日志失败: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public void clearApiCache(Long apiId) {
        // TODO: 实现缓存清除（Phase 4）
        log.info("缓存清除功能待实现: apiId={}", apiId);
    }

    /**
     * 生成基本信息文档
     */
    private String generateBasicInfo(ErpApiConfig config) {
        StringBuilder sb = new StringBuilder();
        sb.append("API名称: ").append(config.getApiName()).append("\n");
        sb.append("API路径: ").append(config.getApiPath()).append("\n");
        sb.append("HTTP方法: ").append(config.getApiMethod()).append("\n");
        sb.append("描述: ").append(config.getApiDesc()).append("\n");
        sb.append("版本: ").append(config.getApiVersion()).append("\n");
        sb.append("结果类型: ").append(config.getResultType()).append("\n");
        sb.append("支持分页: ").append(config.getSupportPagination() == 1 ? "是" : "否").append("\n");
        return sb.toString();
    }

    /**
     * 生成参数信息文档
     */
    private String generateParamsInfo(List<ErpApiParam> params) {
        if (params == null || params.isEmpty()) {
            return "无参数";
        }

        StringBuilder sb = new StringBuilder();
        sb.append("参数列表:\n");
        for (ErpApiParam param : params) {
            sb.append("- ").append(param.getParamName())
              .append(" (").append(param.getParamType()).append(")")
              .append(": ").append(param.getParamDesc())
              .append(param.getIsRequired() == 1 ? " [必填]" : "")
              .append("\n");
        }
        return sb.toString();
    }
}