package com.sundot.airport.web.controller.ledger;

import com.sundot.airport.common.annotation.Log;
import com.sundot.airport.common.core.controller.BaseController;
import com.sundot.airport.common.enums.BusinessType;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;

/**
 * 台账导入模板下载
 * GET /ledger/template             → 下载合并模板（全部20个Sheet）
 * GET /ledger/template?type={key} → 下载单个台账模板
 */
@RestController
@RequestMapping("/ledger/template")
public class LedgerTemplateController extends BaseController {

    // ── 模板定义 ────────────────────────────────────────────────────────

    private static final Map<String, String> KEY_TO_SHEET;   // 业务key → Sheet名
    private static final Map<String, Integer> KEY_TO_HEADS;  // 业务key → 表头行数
    private static final Map<String, String[]> KEY_TO_COLS;  // 业务key → 列名数组

    static {
        Map<String, String> nm = new LinkedHashMap<>();
        Map<String, Integer> hm = new LinkedHashMap<>();
        Map<String, String[]> cm = new LinkedHashMap<>();

        // 1. 部门监察问题记录表 (25列)
        nm.put("supervisionProblem", "部门监察问题记录表");
        hm.put("supervisionProblem", 2);
        cm.put("supervisionProblem", new String[]{
            "时间","区域","工作点","岗位","责任人","问题描述","问题类型","整改措施","依据","问题层级",
            "班组","队室质控员","质控推送队室负责人","附件","整改情况","佐证材料","本月内发生问题次数",
            "上月质控问题超过三次人员","检查人员","分管质控经理","录入时间","部门培训教员","队室内勤",
            "发送至相关人员","队室负责人"
        });

        // 2. 队室三级质控巡查记录表 (21列)
        nm.put("patrolInspection", "队室三级质控巡查记录表");
        hm.put("patrolInspection", 2);
        cm.put("patrolInspection", new String[]{
            "巡查日期","巡查区域","巡查工作点","巡查时间段","巡查岗位","被检查人员","有无问题","检查情况描述",
            "类型","整改措施","附件","整改情况","佐证材料","班组","责任组长",
            "队室质控员","队室负责人","填报人","队室内勤","填报时间","发送至相关人员"
        });

        // 3. 部门实时质控拦截情况记录表 (29列)
        nm.put("realtimeInterception", "部门实时质控拦截情况记录表");
        hm.put("realtimeInterception", 2);
        cm.put("realtimeInterception", new String[]{
            "时间","区域","工作点","岗位","责任人","实时质控拦截物品","个数","问题类型","整改措施","问题层级",
            "班组","附件","问题类别","个人复盘","队室复盘","队室质控员","质控推送队室负责人","开机年限",
            "责任人开机年龄","发送至相关人员","本月内发生问题次数","上月发生次数","实时图像漏检难易度",
            "检查人员","部门培训教员","分管质控经理","队室内勤","备注","队室负责人"
        });

        // 4. 服务巡查 (22列)
        nm.put("servicePatrol", "服务巡查");
        hm.put("servicePatrol", 2);
        cm.put("servicePatrol", new String[]{
            "时间","区域","工作点","岗位","责任人","问题描述","问题类型","整改措施","班组","问题层级",
            "队室服务联络人","服务推送队室负责人","附件","整改情况","佐证材料","本月内发生问题次数",
            "上月服务问题超三次人员","检查人员","分管服务经理","发送至相关人员","队室内勤","队室负责人"
        });

        // 5. 投诉情况 (13列)
        nm.put("complaint", "投诉情况");
        hm.put("complaint", 2);
        cm.put("complaint", new String[]{
            "时间","航班号","旅客姓名","班组","责任人","投诉情况","旅客诉求","类别","渠道来源",
            "是否有责","处理进度","责任队长","队室内勤"
        });

        // 6. 安保测试记录表（部门）(19列)
        nm.put("securityTest", "安保测试记录表（部门）");
        hm.put("securityTest", 2);
        cm.put("securityTest", new String[]{
            "开展时间","测试区域","测试通道","测试项目","被测试人员","被测试岗位","测试物品","图片或视频",
            "是否通过","层级","整改措施","扣分","整改材料","班组","推送队室质控员","推送质控队长",
            "队室内勤","推送按钮","队室负责人"
        });

        // 7. 通道过检率 (横向月份列, 2行表头)
        nm.put("channelPassRate", "通道过检率");
        hm.put("channelPassRate", 2);
        cm.put("channelPassRate", new String[]{
            "组长","班组","内勤",
            "2026年1月平均过检率","2026年2月平均过检率","2026年3月平均过检率",
            "2026年4月平均过检率","2026年5月平均过检率","2026年6月平均过检率",
            "2026年7月平均过检率","2026年8月平均过检率","2026年9月平均过检率",
            "2026年10月平均过检率","2026年11月平均过检率","2026年12月平均过检率"
        });

        // 8. 不安全事件 (11列)
        nm.put("unsafeEvent", "不安全事件");
        hm.put("unsafeEvent", 2);
        cm.put("unsafeEvent", new String[]{
            "时间","事件描述","类别","航班号","责任人","涉及班组","涉及物品","岗位","区域","通道号","图像"
        });

        // 9. 2026查获违规品统计 (20列)
        nm.put("seizureStats", "2026查获违规品统计");
        hm.put("seizureStats", 2);
        cm.put("seizureStats", new String[]{
            "查获时间","地点","通道号","部门/队室","区域","安检员","安检员岗位","值班组长",
            "航班号","航班目的地","机票号","购票时间","旅客姓名","旅客性别","证件号码","旅客来源地",
            "违规类别","物品种类","藏匿部位","数量"
        });

        // 10. 航站楼加分 (7列)
        nm.put("terminalBonus", "航站楼加分");
        hm.put("terminalBonus", 2);
        cm.put("terminalBonus", new String[]{
            "审核日期","姓名","班组","加分分数","队室内勤","总加分数","队室负责人"
        });

        // 11. 成绩收集 (9列)
        nm.put("examScore", "成绩收集");
        hm.put("examScore", 2);
        cm.put("examScore", new String[]{
            "类别","期数","考试人员","理论成绩","图像成绩","班组","分类","备注（补考分数）","队室教员"
        });

        // 12. 小额奖励审批单（1行表头）
        nm.put("rewardApproval", "小额奖励审批单-安检-质控");
        hm.put("rewardApproval", 1);
        cm.put("rewardApproval", new String[]{
            "员工编码","姓名","查获（事件）时间","奖励类别","查获物品","类别（一类/二类）",
            "奖励事由（安全）","人员类别","主要事由简述"
        });

        // 13. 部门奖惩记录表 (5列)
        nm.put("rewardPenalty", "部门奖惩记录表");
        hm.put("rewardPenalty", 2);
        cm.put("rewardPenalty", new String[]{
            "姓名","班组","事由","罚款金额","最后更新时间"
        });

        // 14. 请、休假记录表（特殊）(6列)
        nm.put("leaveSpecial", "请、休假记录表（特殊）");
        hm.put("leaveSpecial", 2);
        cm.put("leaveSpecial", new String[]{
            "姓名","班组","时间（起）","时间（止）","休假类别","天数/时长"
        });

        // 15. 锦旗及感谢信 (7列)
        nm.put("bannerLetter", "锦旗及感谢信");
        hm.put("bannerLetter", 2);
        cm.put("bannerLetter", new String[]{
            "时间","姓名","内容","类别","图片附件","班组","队室内勤"
        });

        // 16. 日常培训记录 (12列)
        nm.put("dailyTraining", "日常培训记录");
        hm.put("dailyTraining", 2);
        cm.put("dailyTraining", new String[]{
            "月度培训记录日期","班组","队室负责教员","队室培训负责队长","课时","项目名称",
            "培训内容","培训教员","培训地点","参训人数","是否完成","备注"
        });

        // 17. 组长履职情况记录表 (6列)
        nm.put("leaderDuty", "组长履职情况记录表");
        hm.put("leaderDuty", 2);
        cm.put("leaderDuty", new String[]{
            "本班点评","问题处置及整改措施","工作提示","提交人","队室负责人","队室质控员"
        });

        // 18. 健康锐兵（2026_3）(21列)
        nm.put("healthSoldier", "健康锐兵（2026_3）");
        hm.put("healthSoldier", 2);
        cm.put("healthSoldier", new String[]{
            "慢性病情况","提交人","近期身体不适情况","是否进行过体检","体检报告是否有异常",
            "近期是否有重大疾病","作息及生活习惯","心理状态","工作压力情况","佐证材料",
            "重大疾病（其他）","体检异常（其他）","近期不适（其他）","慢性病（轻度）","慢性病（重度）",
            "既往病史","既往病史（其他）","提交时间","班组","队室负责人","亚健康人员状态"
        });

        // 19. 宿舍消防安全专项自查表（部门）(11列)
        nm.put("dormFireSafety", "宿舍消防安全专项自查表（部门）");
        hm.put("dormFireSafety", 2);
        cm.put("dormFireSafety", new String[]{
            "检查日期","寝室所在位置","寝室号","自查覆盖项","风险类型排查情况","发现具体隐患",
            "照片","整改责任人","整改完成时间","提交时间","提交人"
        });

        // 20. 培训台账问题通报 (7列)
        nm.put("trainingIssue", "培训台账问题通报");
        hm.put("trainingIssue", 2);
        cm.put("trainingIssue", new String[]{
            "问题台账日期","问题台账内容","具体问题","处理人","班组","二次复核问题","是否完成整改"
        });

        KEY_TO_SHEET = Collections.unmodifiableMap(nm);
        KEY_TO_HEADS = Collections.unmodifiableMap(hm);
        KEY_TO_COLS  = Collections.unmodifiableMap(cm);
    }

    // ── 端点 ─────────────────────────────────────────────────────────────

    @PreAuthorize("@ss.hasPermi('ledger:import:combined')")
    @Log(title = "台账模板下载", businessType = BusinessType.EXPORT)
    @GetMapping
    public void downloadTemplate(
            @RequestParam(required = false) String type,
            HttpServletResponse response) throws Exception {

        boolean combined = (type == null || type.isEmpty());

        if (!combined && !KEY_TO_SHEET.containsKey(type)) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "不支持的模板类型: " + type);
            return;
        }

        String rawName = combined
                ? "旅检三部\"三三\"数字管理平台_模板.xlsx"
                : KEY_TO_SHEET.get(type) + "_导入模板.xlsx";

        try (XSSFWorkbook wb = new XSSFWorkbook()) {
            CellStyle titleStyle  = buildTitleStyle(wb);
            CellStyle headerStyle = buildHeaderStyle(wb);

            if (combined) {
                for (String key : KEY_TO_SHEET.keySet()) {
                    addSheet(wb, key, titleStyle, headerStyle);
                }
            } else {
                addSheet(wb, type, titleStyle, headerStyle);
            }

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition",
                    "attachment; filename=" + URLEncoder.encode(rawName, "UTF-8").replace("+", "%20"));
            wb.write(response.getOutputStream());
        }
    }

    // ── 私有辅助 ──────────────────────────────────────────────────────────

    private void addSheet(XSSFWorkbook wb, String key, CellStyle titleStyle, CellStyle headerStyle) {
        String   sheetName = KEY_TO_SHEET.get(key);
        String[] cols      = KEY_TO_COLS.get(key);
        int      headRows  = KEY_TO_HEADS.getOrDefault(key, 2);

        Sheet sheet = wb.createSheet(sheetName);

        int colCount = cols.length;
        int headerRowIndex;

        if (headRows == 2) {
            // 第1行：大标题（合并单元格）
            Row titleRow = sheet.createRow(0);
            titleRow.setHeightInPoints(22);
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellValue(sheetName);
            titleCell.setCellStyle(titleStyle);
            if (colCount > 1) {
                sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, colCount - 1));
            }
            headerRowIndex = 1;
        } else {
            headerRowIndex = 0;
        }

        // 列头行
        Row headerRow = sheet.createRow(headerRowIndex);
        headerRow.setHeightInPoints(20);
        for (int i = 0; i < colCount; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(cols[i]);
            cell.setCellStyle(headerStyle);
            // 列宽：按列名长度自适应（最小16，最大50个字符宽度）
            int charLen = cols[i].length();
            int width = Math.min(Math.max(charLen + 4, 16), 50) * 256;
            sheet.setColumnWidth(i, width);
        }
    }

    private CellStyle buildTitleStyle(XSSFWorkbook wb) {
        CellStyle s = wb.createCellStyle();
        s.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        s.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        s.setAlignment(HorizontalAlignment.CENTER);
        s.setVerticalAlignment(VerticalAlignment.CENTER);
        Font f = wb.createFont();
        f.setBold(true);
        f.setFontHeightInPoints((short) 12);
        s.setFont(f);
        return s;
    }

    private CellStyle buildHeaderStyle(XSSFWorkbook wb) {
        CellStyle s = wb.createCellStyle();
        s.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
        s.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        s.setAlignment(HorizontalAlignment.CENTER);
        s.setVerticalAlignment(VerticalAlignment.CENTER);
        s.setBorderBottom(BorderStyle.THIN);
        s.setBorderTop(BorderStyle.THIN);
        s.setBorderLeft(BorderStyle.THIN);
        s.setBorderRight(BorderStyle.THIN);
        Font f = wb.createFont();
        f.setBold(true);
        f.setFontHeightInPoints((short) 10);
        s.setFont(f);
        return s;
    }
}