package com.zksy.web.controller.gasbasic;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zksy.base.domain.*;
import com.zksy.base.mapper.*;
import com.zksy.common.annotation.Anonymous;
import com.zksy.common.core.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;

@RestController
@RequestMapping("/api/drill/practical")
@Api(tags = "演练管理-实战演练")
public class DrillPracticalController {

    @Autowired private DrillPracticalTemplateMapper templateMapper;
    @Autowired private DrillPracticalPlanMapper planMapper;
    @Autowired private DrillPracticalResultMapper resultMapper;
    @Autowired private DrillPracticalRecordMapper recordMapper;
    @Autowired private DrillPracticalMonitoringMapper monitoringMapper;
    @Autowired private ObjectMapper objectMapper;

    // ============================================================
    // 一、演练模板 CRUD
    // ============================================================
    @GetMapping("/template")
    @Anonymous
    public AjaxResult templates() {
        return AjaxResult.success(templateMapper.selectList(
            new LambdaQueryWrapper<DrillPracticalTemplate>()
                .orderByDesc(DrillPracticalTemplate::getCreateTime)));
    }

    @PostMapping("/template")
    @Anonymous
    public AjaxResult saveTemplate(@RequestBody DrillPracticalTemplate t) {
        t.setCreateTime(LocalDateTime.now());
        templateMapper.insert(t);
        return AjaxResult.success(t.getId());
    }

    @PutMapping("/template")
    @Anonymous
    public AjaxResult updateTemplate(@RequestBody DrillPracticalTemplate t) {
        templateMapper.updateById(t);
        return AjaxResult.success();
    }

    @DeleteMapping("/template/{id}")
    @Anonymous
    public AjaxResult deleteTemplate(@PathVariable Long id) {
        templateMapper.deleteById(id);
        return AjaxResult.success();
    }

    // ============================================================
    // 二、演练计划 CRUD
    // ============================================================
    @GetMapping("/plan")
    @Anonymous
    public AjaxResult plans() {
        return AjaxResult.success(planMapper.selectList(
            new LambdaQueryWrapper<DrillPracticalPlan>()
                .orderByDesc(DrillPracticalPlan::getCreateTime)));
    }

    @PostMapping("/plan")
    @Anonymous
    public AjaxResult savePlan(@RequestBody DrillPracticalPlan p) {
        p.setCreateTime(LocalDateTime.now());
        p.setUpdateTime(LocalDateTime.now());
        if (p.getStatus() == null) p.setStatus("计划中");
        if (p.getProgress() == null) p.setProgress(0);
        if (p.getParticipantCount() == null) p.setParticipantCount(0);
        planMapper.insert(p);
        return AjaxResult.success(p.getId());
    }

    @PutMapping("/plan")
    @Anonymous
    public AjaxResult updatePlan(@RequestBody DrillPracticalPlan p) {
        p.setUpdateTime(LocalDateTime.now());
        planMapper.updateById(p);
        return AjaxResult.success();
    }

    @DeleteMapping("/plan/{id}")
    @Anonymous
    public AjaxResult deletePlan(@PathVariable Long id) {
        planMapper.deleteById(id);
        // 同时删除关联的演练记录和监测数据
        List<DrillPracticalRecord> records = recordMapper.selectList(
            new LambdaQueryWrapper<DrillPracticalRecord>()
                .eq(DrillPracticalRecord::getPlanId, id));
        for (DrillPracticalRecord r : records) {
            monitoringMapper.delete(new LambdaQueryWrapper<DrillPracticalMonitoring>()
                .eq(DrillPracticalMonitoring::getRecordId, r.getId()));
        }
        recordMapper.delete(new LambdaQueryWrapper<DrillPracticalRecord>()
            .eq(DrillPracticalRecord::getPlanId, id));
        return AjaxResult.success();
    }

    // ============================================================
    // 三、演练计划状态更新
    // ============================================================
    @PutMapping("/plan/status")
    @Anonymous
    @ApiOperation("更新演练计划状态")
    public AjaxResult updatePlanStatus(@RequestParam Long planId, @RequestParam String status) {
        DrillPracticalPlan plan = planMapper.selectById(planId);
        if (plan != null) {
            plan.setStatus(status);
            plan.setUpdateTime(LocalDateTime.now());
            if ("已完成".equals(status)) {
                plan.setProgress(100);
            } else if ("进行中".equals(status) && (plan.getProgress() == null || plan.getProgress() == 0)) {
                plan.setProgress(10);
            }
            planMapper.updateById(plan);
        }
        return AjaxResult.success();
    }

    // ============================================================
    // 四、演练记录 CRUD
    // ============================================================
    @GetMapping("/record/{planId}")
    @Anonymous
    @ApiOperation("按计划ID获取演练记录")
    public AjaxResult getRecord(@PathVariable Long planId) {
        DrillPracticalRecord record = recordMapper.selectOne(
            new LambdaQueryWrapper<DrillPracticalRecord>()
                .eq(DrillPracticalRecord::getPlanId, planId)
                .orderByDesc(DrillPracticalRecord::getCreateTime)
                .last("LIMIT 1"));
        if (record == null) {
            return AjaxResult.success(null);
        }
        // 将 JSON 字符串字段解析为对象后返回
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("id", record.getId());
        result.put("planId", record.getPlanId());
        result.put("drillProjectName", record.getDrillProjectName());
        result.put("recordTime", record.getRecordTime());
        result.put("drillType", record.getDrillType());
        result.put("participatingDept", record.getParticipatingDept());
        result.put("responsiblePerson", record.getResponsiblePerson());
        result.put("status", record.getStatus());
        result.put("reportTime", record.getReportTime());
        result.put("reportMethod", record.getReportMethod());
        result.put("reporter", record.getReporter());
        result.put("contactPhone", record.getContactPhone());
        result.put("eventLocation", record.getEventLocation());
        result.put("eventDescription", record.getEventDescription());
        result.put("releaseContent", record.getReleaseContent());
        result.put("dispatchInfo", parseJson(record.getDispatchInfo()));
        result.put("decisionInfo", parseJson(record.getDecisionInfo()));
        result.put("releaseChannels", parseJsonArray(record.getReleaseChannels()));
        result.put("actions", parseJsonArray(record.getActions()));
        return AjaxResult.success(result);
    }

    @PostMapping("/record")
    @Anonymous
    @ApiOperation("新建演练记录")
    public AjaxResult saveRecord(@RequestBody Map<String, Object> body) {
        DrillPracticalRecord record = new DrillPracticalRecord();
        mapToRecord(body, record);
        record.setCreateTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        recordMapper.insert(record);
        return AjaxResult.success(record.getId());
    }

    @PutMapping("/record")
    @Anonymous
    @ApiOperation("更新演练记录")
    public AjaxResult updateRecord(@RequestBody Map<String, Object> body) {
        Long id = toLong(body.get("id"));
        if (id == null) return AjaxResult.error("记录ID不能为空");
        DrillPracticalRecord record = recordMapper.selectById(id);
        if (record == null) return AjaxResult.error("记录不存在");
        mapToRecord(body, record);
        record.setUpdateTime(LocalDateTime.now());
        recordMapper.updateById(record);
        return AjaxResult.success();
    }

    // ============================================================
    // 五、监测数据 CRUD
    // ============================================================
    @GetMapping("/monitoring/{recordId}")
    @Anonymous
    @ApiOperation("按记录ID获取监测数据列表")
    public AjaxResult monitoring(@PathVariable Long recordId) {
        return AjaxResult.success(monitoringMapper.selectList(
            new LambdaQueryWrapper<DrillPracticalMonitoring>()
                .eq(DrillPracticalMonitoring::getRecordId, recordId)
                .orderByDesc(DrillPracticalMonitoring::getCreateTime)));
    }

    @PostMapping("/monitoring")
    @Anonymous
    @ApiOperation("保存/更新监测数据")
    public AjaxResult saveMonitoring(@RequestBody DrillPracticalMonitoring m) {
        if (m.getId() != null) {
            monitoringMapper.updateById(m);
        } else {
            m.setCreateTime(LocalDateTime.now());
            monitoringMapper.insert(m);
        }
        return AjaxResult.success(m.getId());
    }

    @DeleteMapping("/monitoring/{id}")
    @Anonymous
    @ApiOperation("删除监测数据")
    public AjaxResult deleteMonitoring(@PathVariable Long id) {
        monitoringMapper.deleteById(id);
        return AjaxResult.success();
    }

    // ============================================================
    // 六、分析评估
    // ============================================================
    @GetMapping("/analysis/{planId}")
    @Anonymous
    @ApiOperation("获取演练分析结果")
    public AjaxResult getAnalysis(@PathVariable Long planId) {
        DrillPracticalResult result = resultMapper.selectOne(
            new LambdaQueryWrapper<DrillPracticalResult>()
                .eq(DrillPracticalResult::getPlanId, planId)
                .orderByDesc(DrillPracticalResult::getCreateTime)
                .last("LIMIT 1"));
        if (result == null) {
            return AjaxResult.success(null);
        }
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("id", result.getId());
        data.put("planId", result.getPlanId());
        data.put("skillScore", result.getSkillScore());
        data.put("equipmentScore", result.getEquipmentScore());
        data.put("responseScore", result.getResponseScore());
        data.put("cooperationScore", result.getCooperationScore());
        data.put("totalTasks", result.getTotalTasks());
        data.put("completedTasks", result.getCompletedTasks());
        data.put("completionRate", result.getCompletionRate());
        data.put("overtimeTasks", result.getOvertimeTasks());
        data.put("overallLevel", result.getOverallLevel());
        data.put("evalConclusion", result.getEvalConclusion());
        data.put("improvementSuggestions", parseJsonArray(result.getImprovementSuggestions()));
        data.put("analyzeTime", result.getEvalTime() != null
            ? result.getEvalTime().toString() : null);
        return AjaxResult.success(data);
    }

    @PostMapping("/analysis")
    @Anonymous
    @ApiOperation("发送演练数据至分析评估（生成分析结果）")
    public AjaxResult sendAnalysis(@RequestBody Map<String, Object> body) {
        Long planId = toLong(body.get("planId"));
        if (planId == null) return AjaxResult.error("计划ID不能为空");

        // 先保存/更新演练记录
        DrillPracticalRecord record = recordMapper.selectOne(
            new LambdaQueryWrapper<DrillPracticalRecord>()
                .eq(DrillPracticalRecord::getPlanId, planId)
                .orderByDesc(DrillPracticalRecord::getCreateTime)
                .last("LIMIT 1"));
        boolean isNew = (record == null);
        if (isNew) record = new DrillPracticalRecord();
        mapToRecord(body, record);
        if (isNew) {
            record.setCreateTime(LocalDateTime.now());
            recordMapper.insert(record);
        } else {
            record.setUpdateTime(LocalDateTime.now());
            recordMapper.updateById(record);
        }

        // 基于演练数据生成分析结果
        List<?> monitoringInfo = (List<?>) body.get("monitoringInfo");
        int monCount = monitoringInfo != null ? monitoringInfo.size() : 0;

        Object dispatchInfo = body.get("dispatchInfo");
        Object decisionInfo = body.get("decisionInfo");
        Object releaseChannels = body.get("releaseChannels");
        String releaseContent = (String) body.get("releaseContent");
        List<?> actions = (List<?>) body.get("actions");

        // 查找已有结果记录
        DrillPracticalResult result = resultMapper.selectOne(
            new LambdaQueryWrapper<DrillPracticalResult>()
                .eq(DrillPracticalResult::getPlanId, planId)
                .orderByDesc(DrillPracticalResult::getCreateTime)
                .last("LIMIT 1"));
        boolean newResult = (result == null);
        if (newResult) result = new DrillPracticalResult();
        result.setPlanId(planId);

        // 生成评分（基于数据完整度）
        int score = 60;
        if (monCount > 0) score += Math.min(15, monCount * 3);
        if (dispatchInfo != null) score += 8;
        if (decisionInfo != null) score += 8;
        if (releaseChannels != null && releaseContent != null && !releaseContent.isEmpty()) score += 5;
        if (score > 98) score = 98;

        result.setSkillScore(score);
        result.setEquipmentScore(Math.max(60, score - 7));
        result.setResponseScore(Math.max(65, score - 3));
        result.setCooperationScore(Math.max(62, score - 5));
        result.setTotalTasks(5 + monCount);
        result.setCompletedTasks(dispatchInfo != null && decisionInfo != null ? 5 + monCount : 3 + monCount);
        int compRate = result.getTotalTasks() > 0
            ? (result.getCompletedTasks() * 100 / result.getTotalTasks()) : 0;
        result.setCompletionRate(compRate);
        result.setOvertimeTasks(Math.max(0, monCount / 5));
        result.setOverallLevel(score >= 90 ? "优秀" : score >= 80 ? "良好" : score >= 70 ? "合格" : "待改进");
        result.setEvalConclusion(
            "本次演练整体表现" + result.getOverallLevel() + "，"
            + "共录入监测数据" + monCount + "条，"
            + (dispatchInfo != null ? "指挥调度信息已录入，" : "指挥调度信息缺失，")
            + (decisionInfo != null ? "决策信息已录入。" : "决策信息缺失。")
            + "任务完成率" + compRate + "%。"
        );
        List<String> suggestions = new ArrayList<>();
        if (monCount < 3) suggestions.add("增加监测数据采集密度，提高演练覆盖范围");
        if (dispatchInfo == null) suggestions.add("完善指挥调度信息记录");
        if (decisionInfo == null) suggestions.add("加强决策信息录入规范");
        if (compRate < 80) suggestions.add("提高任务完成率，减少超时任务");
        suggestions.add("加强多部门协同配合训练");
        suggestions.add("定期复盘演练过程，持续优化应急预案");
        try {
            result.setImprovementSuggestions(objectMapper.writeValueAsString(suggestions));
        } catch (Exception e) {
            result.setImprovementSuggestions("[]");
        }
        result.setEvalTime(LocalDateTime.now());
        if (newResult) {
            result.setCreateTime(LocalDateTime.now());
            resultMapper.insert(result);
        } else {
            resultMapper.updateById(result);
        }
        return AjaxResult.success("分析数据已发送，评估结果已生成");
    }

    // ============================================================
    // 七、导出分析报告
    // ============================================================
    @GetMapping("/report/{planId}")
    @Anonymous
    @ApiOperation("导出演练分析报告")
    public ResponseEntity<byte[]> exportReport(@PathVariable Long planId) {
        DrillPracticalPlan plan = planMapper.selectById(planId);
        DrillPracticalResult result = resultMapper.selectOne(
            new LambdaQueryWrapper<DrillPracticalResult>()
                .eq(DrillPracticalResult::getPlanId, planId)
                .orderByDesc(DrillPracticalResult::getCreateTime)
                .last("LIMIT 1"));
        DrillPracticalRecord record = recordMapper.selectOne(
            new LambdaQueryWrapper<DrillPracticalRecord>()
                .eq(DrillPracticalRecord::getPlanId, planId)
                .orderByDesc(DrillPracticalRecord::getCreateTime)
                .last("LIMIT 1"));
        List<DrillPracticalMonitoring> monList = new ArrayList<>();
        if (record != null) {
            monList = monitoringMapper.selectList(
                new LambdaQueryWrapper<DrillPracticalMonitoring>()
                    .eq(DrillPracticalMonitoring::getRecordId, record.getId()));
        }

        StringBuilder sb = new StringBuilder();
        sb.append("=".repeat(50)).append("\n");
        sb.append("           实战演练分析报告\n");
        sb.append("=".repeat(50)).append("\n\n");
        sb.append("演练名称：").append(plan != null ? plan.getName() : "—").append("\n");
        sb.append("演练类型：实战演练\n");
        sb.append("所属系统：").append(plan != null ? plan.getCategory() : "—").append("\n");
        if (plan != null && plan.getEndTime() != null) {
            sb.append("完成时间：").append(plan.getEndTime()).append("\n");
        }
        sb.append("\n--- 演练记录 ---\n");
        if (record != null) {
            sb.append("记录时间：").append(record.getRecordTime()).append("\n");
            sb.append("参演部门：").append(record.getParticipatingDept()).append("\n");
            sb.append("演练状态：").append(record.getStatus()).append("\n");
            sb.append("事件描述：").append(record.getEventDescription()).append("\n");
        } else {
            sb.append("（暂无演练记录）\n");
        }
        sb.append("\n--- 监测数据 (").append(monList.size()).append("条) ---\n");
        for (DrillPracticalMonitoring m : monList) {
            sb.append("  - ").append(m.getSensorType())
              .append(" | ").append(m.getLocation())
              .append(" | 值: ").append(m.getValue()).append(m.getUnit())
              .append(" | 等级: ").append(m.getAlarmLevel())
              .append(" | 时间: ").append(m.getTime()).append("\n");
        }
        sb.append("\n--- 分析评估 ---\n");
        if (result != null) {
            sb.append("综合等级：").append(result.getOverallLevel()).append("\n");
            sb.append("技能掌握：").append(result.getSkillScore()).append("/100\n");
            sb.append("装备使用：").append(result.getEquipmentScore()).append("/100\n");
            sb.append("响应时效：").append(result.getResponseScore()).append("/100\n");
            sb.append("协同配合：").append(result.getCooperationScore()).append("/100\n");
            sb.append("任务总数：").append(result.getTotalTasks()).append("\n");
            sb.append("完成任务：").append(result.getCompletedTasks()).append("\n");
            sb.append("完成率：").append(result.getCompletionRate()).append("%\n");
            sb.append("超时任务：").append(result.getOvertimeTasks()).append("\n");
            sb.append("\n评估结论：").append(result.getEvalConclusion()).append("\n");
        } else {
            sb.append("（暂无分析数据）\n");
        }
        sb.append("\n").append("=".repeat(50)).append("\n");
        sb.append("报告生成时间：").append(LocalDateTime.now()).append("\n");

        byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_PLAIN);
        headers.set("Content-Disposition",
            "attachment; filename=drill_report_" + planId + ".txt");
        return ResponseEntity.ok().headers(headers).body(bytes);
    }

    // ============================================================
    // 八、原有结果查询（保留，兼容旧前端）
    // ============================================================
    @GetMapping("/result/{planId}")
    @Anonymous
    public AjaxResult result(@PathVariable Long planId) {
        return AjaxResult.success(resultMapper.selectOne(
            new LambdaQueryWrapper<DrillPracticalResult>()
                .eq(DrillPracticalResult::getPlanId, planId)
                .orderByDesc(DrillPracticalResult::getCreateTime)
                .last("LIMIT 1")));
    }

    // ============================================================
    // 私有工具方法
    // ============================================================
    private void mapToRecord(Map<String, Object> body, DrillPracticalRecord r) {
        r.setPlanId(toLong(body.get("planId")));
        r.setDrillProjectName((String) body.get("drillProjectName"));
        r.setRecordTime((String) body.get("recordTime"));
        r.setDrillType((String) body.get("drillType"));
        r.setParticipatingDept((String) body.get("participatingDept"));
        r.setResponsiblePerson((String) body.get("responsiblePerson"));
        r.setStatus((String) body.get("status"));
        r.setReportTime((String) body.get("reportTime"));
        r.setReportMethod((String) body.get("reportMethod"));
        r.setReporter((String) body.get("reporter"));
        r.setContactPhone((String) body.get("contactPhone"));
        r.setEventLocation((String) body.get("eventLocation"));
        r.setEventDescription((String) body.get("eventDescription"));
        r.setDispatchInfo(toJsonStr(body.get("dispatchInfo")));
        r.setDecisionInfo(toJsonStr(body.get("decisionInfo")));
        r.setReleaseChannels(toJsonStr(body.get("releaseChannels")));
        r.setReleaseContent((String) body.get("releaseContent"));
        r.setActions(toJsonStr(body.get("actions")));
    }

    private Object parseJson(String json) {
        if (json == null || json.isEmpty()) return null;
        try { return objectMapper.readValue(json, Object.class); }
        catch (Exception e) { return null; }
    }

    private List<?> parseJsonArray(String json) {
        if (json == null || json.isEmpty()) return null;
        try { return objectMapper.readValue(json, List.class); }
        catch (Exception e) { return null; }
    }

    private String toJsonStr(Object obj) {
        if (obj == null) return null;
        if (obj instanceof String) return (String) obj;
        try { return objectMapper.writeValueAsString(obj); }
        catch (Exception e) { return null; }
    }

    private Long toLong(Object val) {
        if (val == null) return null;
        if (val instanceof Number) return ((Number) val).longValue();
        try { return Long.parseLong(val.toString()); }
        catch (Exception e) { return null; }
    }
}
