package com.goldenwater.slaj.acci.controller;

import java.util.List;
import java.util.Map;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.goldenwater.common.annotation.Log;
import com.goldenwater.common.core.controller.BaseController;
import com.goldenwater.common.core.domain.AjaxResult;
import com.goldenwater.common.core.page.TableDataInfo;
import com.goldenwater.common.enums.BusinessType;
import com.goldenwater.common.utils.poi.ExcelUtil;
import com.goldenwater.slaj.acci.domain.BisAcciExpRep;
import com.goldenwater.slaj.acci.domain.ObjAcci;
import com.goldenwater.slaj.acci.domain.ObjAcciVo;
import com.goldenwater.slaj.acci.service.IBisAcciExpRepService;
import com.goldenwater.slaj.acci.service.IObjAcciService;

/**
 * 事故对象
 */
@RestController
@RequestMapping("/acci/objacci")
public class ObjAcciController extends BaseController {
    @Autowired
    private IObjAcciService objAcciService;

    @Autowired
    private IBisAcciExpRepService bisAcciExpRepService;

    @GetMapping("/list")
    public TableDataInfo list(ObjAcciVo objAcciVo) {
        startPage();
        List<ObjAcciVo> list = objAcciService.selectObjAcciList(objAcciVo);
        return getDataTable(list);
    }

    @GetMapping("/{guid}")
    public AjaxResult getInfo(@PathVariable String guid) {
        return AjaxResult.success(objAcciService.selectObjAcciByGuid(guid));
    }

    @PostMapping
    public AjaxResult add(@RequestBody ObjAcci objAcci) {
        return toAjax(objAcciService.insertObjAcci(objAcci));
    }

    @PutMapping
    public AjaxResult edit(@RequestBody ObjAcci objAcci) {
        return toAjax(objAcciService.updateObjAcci(objAcci));
    }

    @DeleteMapping("/{guids}")
    public AjaxResult remove(@PathVariable String[] guids) {
        return toAjax(objAcciService.deleteObjAcciByGuids(guids));
    }

    @Log(title = "事故对象管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('acci:objacci:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, ObjAcciVo objAcciVo) {
        List<ObjAcciVo> list = objAcciService.selectObjAcciList(objAcciVo);
        ExcelUtil<ObjAcciVo> util = new ExcelUtil<ObjAcciVo>(ObjAcciVo.class);
        util.exportExcel(response, list, "事故对象数据");
    }

    @PostMapping("/compoundSave")
    public AjaxResult compoundSave(@RequestBody Map<String, Object> params) {
        try {
            return toAjax(objAcciService.compoundSave(params));
        } catch (Exception e) {
            return AjaxResult.error("保存失败：" + e.getMessage());
        }
    }

    /**
     * 事故催报 — 上级单位向下级单位发送催促通知，提醒下级及时上报本月事故月报。
     * 水利行业采用逐级上报体系，本级月报未上报将阻塞上级汇总进度，因此需要催报机制。
     */
    @Log(title = "事故管理", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('acci:objacci:edit')")
    @PutMapping("/pushForward")
    public AjaxResult pushForward(@RequestBody ObjAcci objAcci) {
        return toAjax(objAcciService.updateObjAcci(objAcci));
    }

    /**
     * 事故补报 — 首次快报之后，事故详情进一步明确时进行补充报告。
     * 生产安全事故要求在事发后1小时内快报，随后24小时内补报详细信息（伤亡人数、经济损失等）。
     * 补报与快报共享同一事故主表，通过扩展表 {@link BisAcciExpRep} 存储补充字段。
     */
    @Log(title = "事故管理", businessType = BusinessType.INSERT)
    @PreAuthorize("@ss.hasPermi('acci:objacci:add')")
    @PostMapping("/insertRep")
    public AjaxResult insertRep(@RequestBody BisAcciExpRep bisAcciExpRep) {
        return toAjax(bisAcciExpRepService.insertBisAcciExpRep(bisAcciExpRep));
    }

    /**
     * 事故统计汇总 — 按事故等级（1-一般/2-较大/3-重大/4-特大）聚合统计各等级事故数量。
     * 该接口面向首页看板，让监管单位快速掌握辖区内事故的严重程度分布，便于分级处置。
     */
    @GetMapping("/summary")
    public AjaxResult summary(ObjAcciVo objAcciVo) {
        List<ObjAcciVo> all = objAcciService.selectObjAcciList(objAcciVo);
        int total = all.size();
        long general = all.stream().filter(a -> "1".equals(a.getAcciGrad())).count();
        long major = all.stream().filter(a -> "2".equals(a.getAcciGrad())).count();
        long heavy = all.stream().filter(a -> "3".equals(a.getAcciGrad())).count();
        long special = all.stream().filter(a -> "4".equals(a.getAcciGrad())).count();
        java.util.Map<String, Object> result = new java.util.HashMap<>();
        result.put("total", total);
        result.put("general", general);
        result.put("major", major);
        result.put("heavy", heavy);
        result.put("special", special);
        return AjaxResult.success(result);
    }

    /**
     * 按事故类别分组统计 — 根据 acciCate 字段（如：物体打击、机械伤害、高处坠落等）汇总每类事故的发生频次。
     * 用于分析事故类型分布，辅助制定专项安全整治措施。
     */
    @GetMapping("/byCategory")
    public AjaxResult byCategory(ObjAcciVo objAcciVo) {
        List<ObjAcciVo> all = objAcciService.selectObjAcciList(objAcciVo);
        java.util.Map<String, Long> cateMap = all.stream()
            .filter(a -> a.getAcciCate() != null)
            .collect(java.util.stream.Collectors.groupingBy(
                ObjAcci::getAcciCate, java.util.stream.Collectors.counting()));
        return AjaxResult.success(cateMap);
    }

    /**
     * 批量上报 — 将选中的事故列表一次性地从本级上报至上级单位。
     * 状态字段 acciStat 从原有值更新为 "2"（已上报），上报后本级不可再修改，仅上级可退回归档。
     * 水利安全生产实行逐级上报制度，下级上报是上级汇总的入口。
     */
    @Log(title = "事故管理", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('acci:objacci:edit')")
    @PutMapping("/batchReport")
    public AjaxResult batchReport(@RequestBody Map<String, Object> params) {
        @SuppressWarnings("unchecked")
        List<String> guids = (List<String>) params.get("guids");
        if (guids == null || guids.isEmpty()) {
            return AjaxResult.error("请选择要上报的事故");
        }
        for (String guid : guids) {
            ObjAcci obj = objAcciService.selectObjAcciByGuid(guid);
            if (obj != null) {
                obj.setRepStat("2");
                objAcciService.updateObjAcci(obj);
            }
        }
        return AjaxResult.success("上报成功");
    }

    /**
     * 上报率进度统计 — 计算当前单位下所有事故的"已上报数 / 总数"百分比。
     * 统计口径：acciStat 为 "2" 计为已上报，其余（空/0/1）均计为未上报。
     * 该指标用于上级对下级上报进度的督办考核。
     */
    @GetMapping("/reportProgress")
    public AjaxResult reportProgress() {
        List<ObjAcciVo> all = objAcciService.selectObjAcciList(new ObjAcciVo());
        long total = all.size();
        long reported = all.stream().filter(a -> "2".equals(a.getRepStat())).count();
        Map<String, Object> result = new java.util.HashMap<>();
        result.put("total", total);
        result.put("reported", reported);
        result.put("unreported", total - reported);
        result.put("rate", total > 0 ? String.format("%.1f", reported * 100.0 / total) : "0");
        return AjaxResult.success(result);
    }

    /**
     * 待办事项查询 — 返回当前用户待处理的事故列表。
     * 筛选条件：acciStat 为 null 或 "0"（均表示未上报状态），限前10条。
     * 数据来源为本级事故表中未上报的记录，提示用户仍有未完成的上报任务。
     */
    @GetMapping("/todoList")
    public AjaxResult todoList() {
        List<ObjAcciVo> todo = objAcciService.selectObjAcciList(new ObjAcciVo());
        todo = todo.stream().filter(a -> a.getRepStat() == null || "0".equals(a.getRepStat())).limit(10).toList();
        return AjaxResult.success(todo);
    }

    /**
     * 移动端事故上报 — 专为移动端（手机/PAD）提供的独立上报入口。
     * 与 PC 端上报不同，移动端由前端传入完整的 SSO 用户信息、单位信息等参数，
     * 而非从服务端 Session/Token 中自动获取，以适应移动端无状态请求的场景。
     */
    @Log(title = "事故管理", businessType = BusinessType.INSERT)
    @PostMapping("/mobile/save")
    public AjaxResult mobileSave(@RequestBody ObjAcci objAcci) {
        return toAjax(objAcciService.insertObjAcci(objAcci));
    }

    /**
     * 事故趋势图 — 各月份事故数量统计，用于折线图/柱状图展示。
     */
    @GetMapping("/trendChart")
    public AjaxResult trendChart(@RequestParam(required = false) String startTime,
                                  @RequestParam(required = false) String endTime) {
        Map<String, Object> params = new java.util.HashMap<>();
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        List<Map<String, Object>> list = objAcciService.selectTrendChart(params);
        return AjaxResult.success(list);
    }

    /**
     * 事故类型占比饼图 — 各事故类别（物体打击/机械伤害/高处坠落等）的数量及占比。
     */
    @GetMapping("/catePieChart")
    public AjaxResult catePieChart(@RequestParam(required = false) String startTime,
                                    @RequestParam(required = false) String endTime) {
        Map<String, Object> params = new java.util.HashMap<>();
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        List<Map<String, Object>> list = objAcciService.selectCatePieChart(params);
        return AjaxResult.success(list);
    }

    /**
     * 事故等级占比饼图 — 各事故等级（一般/较大/重大/特大）的数量及占比。
     */
    @GetMapping("/gradPieChart")
    public AjaxResult gradPieChart(@RequestParam(required = false) String startTime,
                                    @RequestParam(required = false) String endTime) {
        Map<String, Object> params = new java.util.HashMap<>();
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        List<Map<String, Object>> list = objAcciService.selectGradPieChart(params);
        return AjaxResult.success(list);
    }

    /**
     * 事故GIS地图数据 — 返回含经纬度的事故点位列表，用于前端地图聚合展示。
     */
    @GetMapping("/gisData")
    public AjaxResult gisData(@RequestParam(required = false) String startTime,
                               @RequestParam(required = false) String endTime) {
        Map<String, Object> params = new java.util.HashMap<>();
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        List<Map<String, Object>> list = objAcciService.selectGisData(params);
        return AjaxResult.success(list);
    }

    /**
     * 事故统计报表 — 按单位维度统计事故数量、伤亡人数、经济损失等指标。
     * 支持按单位性质和时间范围筛选。
     */
    @GetMapping("/statList")
    public TableDataInfo statList(@RequestParam(required = false) String orgNature,
                                  @RequestParam(required = false) String beginTime,
                                  @RequestParam(required = false) String endTime) {
        startPage();
        Map<String, Object> params = new java.util.HashMap<>();
        params.put("orgNature", orgNature);
        params.put("beginTime", beginTime);
        params.put("endTime", endTime);
        List<Map<String, Object>> list = objAcciService.selectAcciStatList(params);
        return getDataTable(list);
    }
}
