package org.hzhub.erp.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.hzhub.erp.common.domain.R;
import org.hzhub.erp.domain.entity.ErpApiConfig;
import org.hzhub.erp.domain.vo.ApiExecutionResult;
import org.hzhub.erp.service.IErpApiService;
import org.hzhub.erp.service.impl.ApiStatsRecorder;
import org.hzhub.erp.service.impl.DynamicApiExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 动态API执行Controller
 *
 * @author HZHub Team
 */
@RestController
@RequestMapping("/erp/dynamic")
@RequiredArgsConstructor
@SaIgnore  // 当前版本暂时忽略认证，后续通过配置表的require_auth字段控制
public class DynamicApiController {

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

    private final IErpApiService erpApiService;
    private final DynamicApiExecutor dynamicApiExecutor;
    private final ApiStatsRecorder apiStatsRecorder;

    /**
     * 动态路由处理（GET方法）- 支持多层级路径
     *
     * @param version API版本（v1/v2）
     * @param request HTTP请求对象
     * @param allParams 所有请求参数
     * @return 执行结果
     */
    @GetMapping("/{version}/**")
    public R<Object> handleDynamicGet(@PathVariable String version,
                                      HttpServletRequest request,
                                      @RequestParam Map<String, Object> allParams) {
        String fullPath = extractFullPath(request, version);
        return executeDynamicApi(fullPath, "GET", allParams, request);
    }

    /**
     * 动态路由处理（POST方法）- 支持多层级路径
     *
     * @param version API版本（v1/v2）
     * @param request HTTP请求对象
     * @param bodyParams 请求体参数
     * @return 执行结果
     */
    @PostMapping("/{version}/**")
    public R<Object> handleDynamicPost(@PathVariable String version,
                                       HttpServletRequest request,
                                       @RequestBody Map<String, Object> bodyParams) {
        String fullPath = extractFullPath(request, version);
        return executeDynamicApi(fullPath, "POST", bodyParams, request);
    }

    /**
     * 从请求中提取完整的API路径
     *
     * @param request HTTP请求对象
     * @param version API版本
     * @return 完整路径（如：/erp/dynamic/v1/customer/brands）
     */
    private String extractFullPath(HttpServletRequest request, String version) {
        String servletPath = request.getServletPath();
        log.debug("Servlet path: {}, version: {}", servletPath, version);
        return servletPath;  // 直接返回完整路径，Spring已正确解析
    }

    /**
     * 执行动态API
     *
     * @param fullPath 完整API路径
     * @param method HTTP方法
     * @param params 参数Map
     * @param request HTTP请求对象
     * @return 执行结果
     */
    private R<Object> executeDynamicApi(String fullPath, String method, Map<String, Object> params, HttpServletRequest request) {
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        ErpApiConfig config = null;

        try {
            // 从完整路径中提取版本号（路径格式：/erp/dynamic/v1/customer/brands）
            String version = fullPath.split("/")[3];  // 第4段是版本号
            String apiPath = fullPath.substring("/erp/dynamic/".length() + version.length() + 1);

            log.info("执行动态API: fullPath={}, method={}, version={}, apiPath={}, params={}",
                fullPath, method, version, apiPath, params);

            // 1. 查询API配置（使用完整路径匹配）
            config = erpApiService.selectApiConfigByPath(fullPath, method, version);
            if (config == null) {
                log.warn("API配置不存在: path={}, method={}, version={}", fullPath, method, version);
                return R.fail("API不存在");
            }

            if (config.getStatus() == 0) {
                log.warn("API已禁用: apiId={}", config.getApiId());
                return R.fail("API已禁用");
            }

            // 2. 权限检查（如果配置了require_auth）
            // TODO: 集成Sa-Token权限验证（Phase 4）
            if (config.getRequireAuth() == 1) {
                log.info("API需要权限验证: permissionCode={}", config.getPermissionCode());
                // StpUtil.checkPermission(config.getPermissionCode());
            }

            // 3. 参数验证与转换
            // TODO: 根据参数配置验证参数（Phase 4）

            // 4. 执行SQL
            ApiExecutionResult executionResult = dynamicApiExecutor.execute(config, params);
            Object result = executionResult.getData();
            String executedSql = executionResult.getExecutedSql();

            // 计算响应时间
            long responseTime = System.currentTimeMillis() - startTime;

            log.info("动态API执行成功: apiId={}, resultType={}, time={}ms",
                config.getApiId(), result.getClass().getSimpleName(), responseTime);
            log.debug("实际执行SQL: {}", executedSql);

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

            // 6. 返回结果
            if (result instanceof R) {
                return (R<Object>) result;
            } else {
                return R.ok(result);
            }

        } catch (SecurityException e) {
            log.error("安全验证失败: {}", e.getMessage());

            // 记录错误统计
            if (config != null) {
                long responseTime = System.currentTimeMillis() - startTime;
                // 错误情况下使用SQL模板作为executedSql
                String executedSql = config.getSqlTemplate();
                apiStatsRecorder.recordError(config.getApiId(), params.toString(), executedSql,
                                             responseTime, e.getMessage(),
                                             getStackTrace(e), getClientIp(request), getUserId(request));
            }

            return R.fail("安全验证失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("动态API执行失败: {}", e.getMessage(), e);

            // 记录错误统计
            if (config != null) {
                long responseTime = System.currentTimeMillis() - startTime;
                // 错误情况下使用SQL模板作为executedSql
                String executedSql = config.getSqlTemplate();
                apiStatsRecorder.recordError(config.getApiId(), params.toString(), executedSql,
                                             responseTime, e.getMessage(),
                                             getStackTrace(e), getClientIp(request), getUserId(request));
            }

            return R.fail("执行失败: " + e.getMessage());
        }
    }

    /**
     * 获取客户端IP（考虑代理和网关）
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }

        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }

        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }

        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");  // Nginx常用的真实IP头
        }

        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();  // 最后使用直接连接的IP
        }

        // 如果通过了多个代理，第一个IP才是真实IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }

        return ip != null ? ip : "unknown";
    }

    /**
     * 获取用户ID（从网关注入的请求头中获取）
     */
    private String getUserId(HttpServletRequest request) {
        // 网关会在验证JWT后注入用户ID
        String userId = request.getHeader("X-User-Id");

        if (userId == null || userId.isEmpty()) {
            // 如果没有网关头，尝试从Sa-Token获取
            try {
                // StpUtil.getLoginIdAsString();  // 如果已集成Sa-Token
                userId = "anonymous";
            } catch (Exception e) {
                userId = "anonymous";
            }
        }

        return userId;
    }

    /**
     * 获取异常堆栈（前500字符）
     */
    private String getStackTrace(Exception e) {
        StringBuilder sb = new StringBuilder();
        for (StackTraceElement element : e.getStackTrace()) {
            sb.append(element.toString()).append("\n");
            if (sb.length() > 500) {
                break;
            }
        }
        return sb.toString();
    }
}