package com.ruoyi.web.controller.public_;

import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.LimitType;
import com.ruoyi.jarvis.service.IInstructionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 公开订单提交控制器
 * 用于接收外部提交的订单信息
 * 特点：
 * 1. 无需登录认证
 * 2. 带接口限流保护
 * 3. 详细的日志记录
 * 4. 只允许使用"单"指令提交订单
 */
@RestController
@RequestMapping("/public/order")
public class PublicOrderController extends BaseController {

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

    private final IInstructionService instructionService;

    public PublicOrderController(IInstructionService instructionService) {
        this.instructionService = instructionService;
    }

    /**
     * 提交订单
     * 
     * 限流策略：
     * - 每个IP半小时（30分钟）最多20次请求
     * - 防止恶意刷单和攻击
     * 
     * @param body 请求体，包含command字段
     * @param request HTTP请求对象，用于获取客户端信息
     * @return 执行结果
     */
    @PostMapping("/submit")
    @RateLimiter(
        key = CacheConstants.RATE_LIMIT_KEY, 
        time = 1800, 
        count = 120, 
        limitType = LimitType.IP
    )
    public AjaxResult submit(@RequestBody Map<String, String> body, HttpServletRequest request) {
        // 获取客户端信息用于日志记录
        String clientIp = getClientIp(request);
        String userAgent = request.getHeader("User-Agent");
        
        // 获取指令内容
        String cmd = body != null ? body.get("command") : null;
        
        // 记录请求日志
        log.info("======================================");
        log.info("公开订单提交 - 开始");
        log.info("客户端IP: {}", clientIp);
        log.info("User-Agent: {}", userAgent);
        log.info("请求时间: {}", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));
        
        // 参数校验
        if (cmd == null || cmd.trim().isEmpty()) {
            log.warn("参数校验失败: 指令内容为空");
            log.info("公开订单提交 - 结束（失败）");
            log.info("======================================");
            return AjaxResult.error("请输入订单信息");
        }
        
        String trimmedCmd = cmd.trim();
        log.info("指令内容长度: {} 字符", trimmedCmd.length());
        log.info("指令内容预览: {}", trimmedCmd.length() > 100 ? trimmedCmd.substring(0, 100) + "..." : trimmedCmd);
        
        // 安全检查：只允许"单"开头的指令
        if (!trimmedCmd.startsWith("单：") && !trimmedCmd.startsWith("单:") && !trimmedCmd.startsWith("单")) {
            log.warn("安全检查失败: 指令不是以'单'开头");
            log.info("公开订单提交 - 结束（拒绝）");
            log.info("======================================");
            return AjaxResult.error("只允许提交订单信息，指令必须以'单：'开头");
        }
        
        // 日期验证：只允许提交今天的订单
        String orderDate = extractOrderDate(trimmedCmd);
        if (orderDate == null) {
            log.warn("日期验证失败: 无法解析订单日期");
            log.info("公开订单提交 - 结束（拒绝）");
            log.info("======================================");
            return AjaxResult.error("订单格式错误，无法识别订单日期");
        }
        
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        if (!orderDate.equals(today)) {
            log.warn("日期验证失败: 订单日期[{}]不是今天[{}]", orderDate, today);
            log.info("公开订单提交 - 结束（拒绝）");
            log.info("======================================");
            return AjaxResult.error("只允许提交今天的订单，订单日期必须是: " + today);
        }
        
        log.info("日期验证通过: 订单日期[{}]", orderDate);
        
        // 获取forceGenerate参数（默认为false）
        boolean forceGenerate = body != null && body.get("forceGenerate") != null && Boolean.parseBoolean(String.valueOf(body.get("forceGenerate")));
        
        // 执行指令
        List<String> result;
        try {
            log.info("开始执行订单指令... forceGenerate={}", forceGenerate);
            result = instructionService.execute(trimmedCmd, forceGenerate);
            log.info("订单指令执行完成");
            
            // 记录执行结果
            if (result != null && !result.isEmpty()) {
                log.info("执行结果条数: {}", result.size());
                for (int i = 0; i < result.size(); i++) {
                    String item = result.get(i);
                    if (item != null) {
                        // 检查是否包含警告标记
                        if (item.contains("[炸弹]")) {
                            log.warn("执行结果[{}]包含警告: {}", i, item);
                        } else if (item.contains("成功")) {
                            log.info("执行结果[{}]: 成功", i);
                        } else {
                            log.info("执行结果[{}]长度: {} 字符", i, item.length());
                        }
                    }
                }
            } else {
                log.warn("执行结果为空");
            }
            
            log.info("公开订单提交 - 结束（成功）");
            log.info("======================================");
            return AjaxResult.success(result);
            
        } catch (Exception e) {
            log.error("执行订单指令时发生异常", e);
            log.error("异常类型: {}", e.getClass().getName());
            log.error("异常消息: {}", e.getMessage());
            log.info("公开订单提交 - 结束（异常）");
            log.info("======================================");
            return AjaxResult.error("订单提交失败: " + e.getMessage());
        }
    }
    
    /**
     * 从订单内容中提取日期
     * 订单格式示例：
     * 单：
     * 2025-01-21 001
     * 备注：...
     * 
     * @param orderContent 订单内容
     * @return 日期字符串（格式：yyyy-MM-dd），如果无法解析则返回null
     */
    private String extractOrderDate(String orderContent) {
        try {
            // 匹配格式：YYYY-MM-DD（在"单："之后的行）
            Pattern pattern = Pattern.compile("单[：:].*(\\d{4}-\\d{2}-\\d{2})");
            Matcher matcher = pattern.matcher(orderContent.replaceAll("\\s+", " "));
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            // 尝试另一种格式：换行后直接是日期
            String[] lines = orderContent.split("\\r?\\n");
            if (lines.length >= 2) {
                String secondLine = lines[1].trim();
                Pattern datePattern = Pattern.compile("^(\\d{4}-\\d{2}-\\d{2})");
                Matcher dateMatcher = datePattern.matcher(secondLine);
                if (dateMatcher.find()) {
                    return dateMatcher.group(1);
                }
            }
            
            return null;
        } catch (Exception e) {
            log.error("解析订单日期时发生异常: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 获取客户端真实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.getRemoteAddr();
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP
        if (ip != null && ip.contains(",")) {
            ip = ip.substring(0, ip.indexOf(",")).trim();
        }
        return ip;
    }
}

