"""
电子取证清单 API

提供取证规则搜索、清单 CRUD、清单导出等功能。
"""
from fastapi import APIRouter, Depends, Query, HTTPException, Request
from fastapi.responses import StreamingResponse, FileResponse
from typing import Optional
import io

from ...core.database import get_db, get_system_db, _has_split_databases
from ...core.permission import require_login
from ...utils.request_utils import safe_json

router = APIRouter()


async def get_system_db_dep():
    """依赖注入：system.db（取证规则等只读参考数据）"""
    async for conn, cur in (get_system_db() if _has_split_databases() else get_db()):
        yield conn, cur


# ── 领域枚举 ──

@router.get("/domains")
async def list_domains(
    user: dict = Depends(require_login),
    db=Depends(get_system_db_dep),
):
    """获取业务领域 + 案件类型筛选项"""
    conn, cur = db
    await cur.execute(
        "SELECT domain, case_type, rule_count FROM evidence_domains ORDER BY domain, case_type"
    )
    rows = await cur.fetchall()

    # 按领域分组
    domain_map: dict = {}
    for row in rows:
        r = dict(row) if not isinstance(row, dict) else row
        d = r["domain"]
        if d not in domain_map:
            domain_map[d] = {"domain": d, "case_types": []}
        domain_map[d]["case_types"].append({
            "case_type": r["case_type"],
            "rule_count": r["rule_count"],
        })

    return {
        "success": True,
        "data": {
            "domains": list(domain_map.values()),
        },
    }


# ── 取证规则搜索 ──

@router.get("/rules")
async def search_rules(
    keyword: Optional[str] = Query(None, description="全文搜索关键词"),
    domain: Optional[str] = Query(None, description="业务领域"),
    case_type: Optional[str] = Query(None, description="案件类型"),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    user: dict = Depends(require_login),
    db=Depends(get_system_db_dep),
):
    """搜索取证规则（全文搜索 + 筛选 + 分页）"""
    conn, cur = db

    conditions = ["is_deleted = 0"]
    params = []

    if domain:
        conditions.append("domain = ?")
        params.append(domain)

    if case_type:
        conditions.append("case_type = ?")
        params.append(case_type)

    if keyword:
        kw = f"%{keyword}%"
        conditions.append(
            "(domain LIKE ? OR case_type LIKE ? OR target_objects LIKE ? OR key_data LIKE ? OR compliance_req LIKE ?)"
        )
        params.extend([kw, kw, kw, kw, kw])

    where = " AND ".join(conditions)

    # 总数
    await cur.execute(f"SELECT COUNT(*) FROM evidence_rules WHERE {where}", params)
    count_row = await cur.fetchone()
    total = count_row[0] if count_row else 0

    # 分页数据
    offset = (page - 1) * page_size
    await cur.execute(
        f"SELECT * FROM evidence_rules WHERE {where} ORDER BY domain, case_type, id LIMIT ? OFFSET ?",
        params + [page_size, offset],
    )
    rows = await cur.fetchall()
    rules = [dict(r) if not isinstance(r, dict) else r for r in rows]

    return {
        "success": True,
        "data": {
            "list": rules,
            "total": total,
            "page": page,
            "pageSize": page_size,
        },
    }


# ── 清单列表 ──

@router.get("/checklists")
async def list_checklists(
    keyword: Optional[str] = Query(None, description="清单标题搜索"),
    status: Optional[str] = Query(None, description="状态筛选"),
    domain: Optional[str] = Query(None, description="领域筛选"),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """获取用户取证清单列表"""
    conn, cur = db
    user_id = str(user.get("id", "1"))

    conditions = ["is_deleted = 0", "user_id = ?"]
    params: list = [user_id]

    if status:
        conditions.append("status = ?")
        params.append(status)

    if domain:
        conditions.append("domain = ?")
        params.append(domain)

    if keyword:
        conditions.append("title LIKE ?")
        params.append(f"%{keyword}%")

    where = " AND ".join(conditions)

    # 总数
    await cur.execute(f"SELECT COUNT(*) FROM evidence_checklists WHERE {where}", params)
    count_row = await cur.fetchone()
    total = count_row[0] if count_row else 0

    # 分页
    offset = (page - 1) * page_size
    await cur.execute(
        f"SELECT * FROM evidence_checklists WHERE {where} ORDER BY updated_at DESC LIMIT ? OFFSET ?",
        params + [page_size, offset],
    )
    rows = await cur.fetchall()
    checklists = [dict(r) if not isinstance(r, dict) else r for r in rows]

    # 附加每个清单的项目统计
    for cl in checklists:
        await cur.execute(
            "SELECT COUNT(*) FROM evidence_checklist_items WHERE checklist_id = ? AND is_deleted = 0",
            (cl["id"],),
        )
        total_row = await cur.fetchone()
        cl["item_total"] = total_row[0] if total_row else 0

        await cur.execute(
            "SELECT COUNT(*) FROM evidence_checklist_items WHERE checklist_id = ? AND is_deleted = 0 AND is_checked = 1",
            (cl["id"],),
        )
        checked_row = await cur.fetchone()
        cl["item_checked"] = checked_row[0] if checked_row else 0

    return {
        "success": True,
        "data": {
            "list": checklists,
            "total": total,
            "page": page,
            "pageSize": page_size,
        },
    }


# ── 创建清单 ──

@router.post("/checklists")
async def create_checklist(
    request: Request,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """创建取证清单（从勾选的规则生成）"""
    conn, cur = db
    user_id = str(user.get("id", "1"))
    body = await safe_json(request)

    title = body.get("title", "").strip()
    if not title:
        raise HTTPException(status_code=400, detail="清单标题不能为空")

    domain = body.get("domain", "")
    case_type = body.get("case_type", "")
    rule_ids = body.get("rule_ids", [])  # 勾选的规则ID列表

    # 创建清单
    await cur.execute(
        """INSERT INTO evidence_checklists (user_id, title, domain, case_type, status)
           VALUES (?, ?, ?, ?, 'draft')""",
        (user_id, title, domain, case_type),
    )

    # 获取自增ID（SQLite兼容）
    await cur.execute("SELECT last_insert_rowid()")
    row = await cur.fetchone()
    checklist_id = row[0] if row else None

    if not checklist_id:
        raise HTTPException(status_code=500, detail="创建清单失败")

    # 从规则生成清单项目
    if rule_ids:
        placeholders = ",".join(["?"] * len(rule_ids))
        # evidence_rules 在 system.db 中，需要单独查询
        if _has_split_databases():
            async for sys_conn, sys_cur in get_system_db():
                await sys_cur.execute(
                    f"SELECT * FROM evidence_rules WHERE id IN ({placeholders}) AND is_deleted = 0",
                    rule_ids,
                )
                rules = await sys_cur.fetchall()
                break
        else:
            await cur.execute(
                f"SELECT * FROM evidence_rules WHERE id IN ({placeholders}) AND is_deleted = 0",
                rule_ids,
            )
            rules = await cur.fetchall()

        sort_order = 0
        for rule in rules:
            r = dict(rule) if not isinstance(rule, dict) else rule
            # 拆分为三类项目
            items_to_insert = []
            if r.get("target_objects"):
                items_to_insert.append(("target", r["target_objects"]))
            if r.get("key_data"):
                items_to_insert.append(("key_data", r["key_data"]))
            if r.get("compliance_req"):
                items_to_insert.append(("compliance", r["compliance_req"]))

            for item_type, content in items_to_insert:
                # 按分号拆分多条
                parts = [p.strip() for p in content.replace("；", ";").split(";") if p.strip()]
                for part in parts:
                    await cur.execute(
                        """INSERT INTO evidence_checklist_items
                           (checklist_id, rule_id, item_type, content, sort_order)
                           VALUES (?, ?, ?, ?, ?)""",
                        (checklist_id, r["id"], item_type, part, sort_order),
                    )
                    sort_order += 1

    await conn.commit()

    return {
        "success": True,
        "data": {"id": checklist_id, "title": title},
    }


# ── 清单详情 ──

@router.get("/checklists/{checklist_id}")
async def get_checklist_detail(
    checklist_id: int,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """获取清单详情（含所有项目）"""
    conn, cur = db
    user_id = str(user.get("id", "1"))

    await cur.execute(
        "SELECT * FROM evidence_checklists WHERE id = ? AND user_id = ? AND is_deleted = 0",
        (checklist_id, user_id),
    )
    cl = await cur.fetchone()
    if not cl:
        raise HTTPException(status_code=404, detail="清单不存在")

    checklist = dict(cl) if not isinstance(cl, dict) else cl

    # 获取项目列表
    await cur.execute(
        "SELECT * FROM evidence_checklist_items WHERE checklist_id = ? AND is_deleted = 0 ORDER BY sort_order, id",
        (checklist_id,),
    )
    items = await cur.fetchall()
    checklist["items"] = [dict(i) if not isinstance(i, dict) else i for i in items]

    # 统计
    checklist["item_total"] = len(checklist["items"])
    checklist["item_checked"] = sum(1 for i in checklist["items"] if i.get("is_checked"))

    return {"success": True, "data": checklist}


# ── 更新清单 ──

@router.put("/checklists/{checklist_id}")
async def update_checklist(
    checklist_id: int,
    request: Request,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """更新清单基本信息"""
    conn, cur = db
    user_id = str(user.get("id", "1"))
    body = await safe_json(request)

    await cur.execute(
        "SELECT id FROM evidence_checklists WHERE id = ? AND user_id = ? AND is_deleted = 0",
        (checklist_id, user_id),
    )
    if not await cur.fetchone():
        raise HTTPException(status_code=404, detail="清单不存在")

    fields = []
    params = []
    for key in ["title", "domain", "case_type", "status", "notes"]:
        if key in body:
            fields.append(f"{key} = ?")
            params.append(body[key])

    if fields:
        fields.append("updated_at = datetime('now')")
        params.append(checklist_id)
        await cur.execute(
            f"UPDATE evidence_checklists SET {', '.join(fields)} WHERE id = ?",
            params,
        )
        await conn.commit()

    return {"success": True, "message": "更新成功"}


# ── 删除清单 ──

@router.delete("/checklists/{checklist_id}")
async def delete_checklist(
    checklist_id: int,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """删除清单（软删除）"""
    conn, cur = db
    user_id = str(user.get("id", "1"))

    await cur.execute(
        "SELECT id FROM evidence_checklists WHERE id = ? AND user_id = ? AND is_deleted = 0",
        (checklist_id, user_id),
    )
    if not await cur.fetchone():
        raise HTTPException(status_code=404, detail="清单不存在")

    await cur.execute(
        "UPDATE evidence_checklists SET is_deleted = 1, updated_at = datetime('now') WHERE id = ?",
        (checklist_id,),
    )
    await cur.execute(
        "UPDATE evidence_checklist_items SET is_deleted = 1, updated_at = datetime('now') WHERE checklist_id = ?",
        (checklist_id,),
    )
    await conn.commit()

    return {"success": True, "message": "删除成功"}


# ── 添加清单项目 ──

@router.post("/checklists/{checklist_id}/items")
async def add_checklist_item(
    checklist_id: int,
    request: Request,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """添加自定义清单项目"""
    conn, cur = db
    user_id = str(user.get("id", "1"))

    await cur.execute(
        "SELECT id FROM evidence_checklists WHERE id = ? AND user_id = ? AND is_deleted = 0",
        (checklist_id, user_id),
    )
    if not await cur.fetchone():
        raise HTTPException(status_code=404, detail="清单不存在")

    body = await safe_json(request)
    content = body.get("content", "").strip()
    if not content:
        raise HTTPException(status_code=400, detail="项目内容不能为空")

    item_type = body.get("item_type", "custom")
    user_note = body.get("user_note", "")

    # 获取当前最大 sort_order
    await cur.execute(
        "SELECT COALESCE(MAX(sort_order), -1) FROM evidence_checklist_items WHERE checklist_id = ? AND is_deleted = 0",
        (checklist_id,),
    )
    max_row = await cur.fetchone()
    next_order = (max_row[0] if max_row else 0) + 1

    await cur.execute(
        """INSERT INTO evidence_checklist_items
           (checklist_id, item_type, content, sort_order, user_note)
           VALUES (?, ?, ?, ?, ?)""",
        (checklist_id, item_type, content, next_order, user_note),
    )
    await cur.execute("SELECT last_insert_rowid()")
    row = await cur.fetchone()
    item_id = row[0] if row else None

    # 更新清单的 updated_at
    await cur.execute(
        "UPDATE evidence_checklists SET updated_at = datetime('now') WHERE id = ?",
        (checklist_id,),
    )
    await conn.commit()

    return {"success": True, "data": {"id": item_id}}


# ── 更新清单项目 ──

@router.put("/checklist-items/{item_id}")
async def update_checklist_item(
    item_id: int,
    request: Request,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """更新清单项目（内容/备注/勾选状态）"""
    conn, cur = db
    user_id = str(user.get("id", "1"))

    # 验证权限
    await cur.execute(
        """SELECT ci.id FROM evidence_checklist_items ci
           JOIN evidence_checklists cl ON ci.checklist_id = cl.id
           WHERE ci.id = ? AND cl.user_id = ? AND ci.is_deleted = 0""",
        (item_id, user_id),
    )
    if not await cur.fetchone():
        raise HTTPException(status_code=404, detail="项目不存在")

    body = await safe_json(request)
    fields = []
    params = []
    for key in ["content", "user_note", "is_checked", "sort_order"]:
        if key in body:
            fields.append(f"{key} = ?")
            params.append(body[key])

    if fields:
        fields.append("updated_at = datetime('now')")
        params.append(item_id)
        await cur.execute(
            f"UPDATE evidence_checklist_items SET {', '.join(fields)} WHERE id = ?",
            params,
        )

        # 同步更新清单的 updated_at
        await cur.execute(
            """UPDATE evidence_checklists SET updated_at = datetime('now')
               WHERE id = (SELECT checklist_id FROM evidence_checklist_items WHERE id = ?)""",
            (item_id,),
        )
        await conn.commit()

    return {"success": True, "message": "更新成功"}


# ── 删除清单项目 ──

@router.delete("/checklist-items/{item_id}")
async def delete_checklist_item(
    item_id: int,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """删除清单项目"""
    conn, cur = db
    user_id = str(user.get("id", "1"))

    await cur.execute(
        """SELECT ci.id, ci.checklist_id FROM evidence_checklist_items ci
           JOIN evidence_checklists cl ON ci.checklist_id = cl.id
           WHERE ci.id = ? AND cl.user_id = ? AND ci.is_deleted = 0""",
        (item_id, user_id),
    )
    row = await cur.fetchone()
    if not row:
        raise HTTPException(status_code=404, detail="项目不存在")

    r = dict(row) if not isinstance(row, dict) else row

    await cur.execute(
        "UPDATE evidence_checklist_items SET is_deleted = 1, updated_at = datetime('now') WHERE id = ?",
        (item_id,),
    )
    await cur.execute(
        "UPDATE evidence_checklists SET updated_at = datetime('now') WHERE id = ?",
        (r["checklist_id"],),
    )
    await conn.commit()

    return {"success": True, "message": "删除成功"}


# ── 导出 Word / PDF ──

def _build_docx_buffer(checklist: dict, items_list: list, user_name: str) -> io.BytesIO:
    """生成 Word 文档并返回 BytesIO buffer"""
    from docx import Document
    from docx.shared import Pt, Inches, RGBColor
    from docx.enum.text import WD_ALIGN_PARAGRAPH

    doc = Document()

    # 设置默认字体
    style = doc.styles["Normal"]
    style.font.name = "宋体"
    style.font.size = Pt(12)

    # 标题
    title = doc.add_heading(level=1)
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = title.add_run("电子取证清单")
    run.font.size = Pt(18)
    run.font.bold = True

    # 基本信息
    doc.add_paragraph("")
    info_table = doc.add_table(rows=5, cols=2)
    info_table.style = "Table Grid"
    info_data = [
        ("清单标题", checklist.get("title", "")),
        ("业务领域", checklist.get("domain", "")),
        ("案件类型", checklist.get("case_type", "")),
        ("创建时间", checklist.get("created_at", "")),
        ("制作人", user_name),
    ]
    for idx, (label, value) in enumerate(info_data):
        info_table.rows[idx].cells[0].text = label
        info_table.rows[idx].cells[1].text = str(value)
        for paragraph in info_table.rows[idx].cells[0].paragraphs:
            for run in paragraph.runs:
                run.font.bold = True

    # 分组展示
    groups = [
        ("target", "一、核心取证对象"),
        ("key_data", "二、关键取证数据"),
        ("compliance", "三、法定合规要求"),
        ("custom", "四、自定义取证项目"),
    ]

    for item_type, group_title in groups:
        group_items = [i for i in items_list if i.get("item_type") == item_type]
        if not group_items:
            continue

        doc.add_paragraph("")
        heading = doc.add_heading(level=2)
        heading.add_run(group_title)

        for item in group_items:
            checkbox = "☑" if item.get("is_checked") else "☐"
            p = doc.add_paragraph()
            p.paragraph_format.space_before = Pt(2)
            p.paragraph_format.space_after = Pt(2)
            run = p.add_run(f"  {checkbox}  {item.get('content', '')}")
            run.font.size = Pt(11)

            if item.get("user_note"):
                note_p = doc.add_paragraph()
                note_p.paragraph_format.left_indent = Inches(0.5)
                note_run = note_p.add_run(f"备注：{item['user_note']}")
                note_run.font.size = Pt(10)
                note_run.font.color.rgb = RGBColor(100, 100, 100)

    # 进度统计
    total = len(items_list)
    checked = sum(1 for i in items_list if i.get("is_checked"))
    doc.add_paragraph("")
    doc.add_paragraph(f"完成进度：{checked}/{total}")

    # 用户备注
    if checklist.get("notes"):
        doc.add_paragraph(f"备注：{checklist['notes']}")

    # 签字栏
    doc.add_paragraph("")
    doc.add_paragraph("")
    sign_table = doc.add_table(rows=1, cols=2)
    sign_table.rows[0].cells[0].text = "制表人签字：____________"
    sign_table.rows[0].cells[1].text = "日期：____________"

    buffer = io.BytesIO()
    doc.save(buffer)
    buffer.seek(0)
    return buffer


def _docx_to_pdf(docx_buffer: io.BytesIO) -> io.BytesIO:
    """将 docx 转为 pdf（尝试多种方式）"""
    import tempfile
    import os

    # 写入临时 docx 文件
    with tempfile.NamedTemporaryFile(suffix=".docx", delete=False) as tmp_docx:
        tmp_docx.write(docx_buffer.read())
        tmp_docx_path = tmp_docx.name

    pdf_path = tmp_docx_path.replace(".docx", ".pdf")

    try:
        # 方式1: 使用 LibreOffice 转换（如果安装了的话）
        import subprocess
        lo_paths = [
            r"C:\Program Files\LibreOffice\program\soffice.exe",
            r"C:\Program Files (x86)\LibreOffice\program\soffice.exe",
            "soffice",  # Linux/Mac PATH 中的
        ]
        lo_exe = None
        for p in lo_paths:
            if os.path.exists(p):
                lo_exe = p
                break
            elif p == "soffice":
                # 检查是否在 PATH 中
                try:
                    subprocess.run([p, "--version"], capture_output=True, timeout=5, creationflags=0x08000000)
                    lo_exe = p
                except (FileNotFoundError, subprocess.TimeoutExpired):
                    continue

        if lo_exe:
            tmp_dir = os.path.dirname(tmp_docx_path)
            subprocess.run(
                [lo_exe, "--headless", "--convert-to", "pdf", "--outdir", tmp_dir, tmp_docx_path],
                capture_output=True,
                timeout=30,
                creationflags=0x08000000,
            )
            if os.path.exists(pdf_path):
                with open(pdf_path, "rb") as f:
                    pdf_buffer = io.BytesIO(f.read())
                pdf_buffer.seek(0)
                return pdf_buffer

        # 方式2: 使用 docx2pdf（需要 Microsoft Word）
        try:
            from docx2pdf import convert as docx2pdf_convert
            docx2pdf_convert(tmp_docx_path, pdf_path)
            if os.path.exists(pdf_path):
                with open(pdf_path, "rb") as f:
                    pdf_buffer = io.BytesIO(f.read())
                pdf_buffer.seek(0)
                return pdf_buffer
        except ImportError:
            pass

        # 方式3: 无法转换，返回 None（调用方会回退到 docx 导出）
        return None

    finally:
        # 清理临时文件
        for p in [tmp_docx_path, pdf_path]:
            try:
                if os.path.exists(p):
                    os.unlink(p)
            except Exception:
                pass


def _build_pdf_buffer(checklist: dict, items_list: list, user_name: str) -> io.BytesIO:
    """用 reportlab 直接生成 PDF（纯 Python，无需外部工具）"""
    from reportlab.lib.pagesizes import A4
    from reportlab.lib.units import mm, cm
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.lib.enums import TA_CENTER, TA_LEFT
    from reportlab.lib.colors import HexColor
    from reportlab.platypus import (
        SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
        HRFlowable,
    )
    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont

    # 注册中文字体
    font_registered = False
    font_paths = [
        ("SimSun", r"C:\Windows\Fonts\simsun.ttc"),
        ("SimHei", r"C:\Windows\Fonts\simhei.ttf"),
        ("MSYH", r"C:\Windows\Fonts\msyh.ttc"),
        ("STSong", r"/System/Library/Fonts/STSong.ttf"),  # macOS
    ]
    for font_name, font_path in font_paths:
        try:
            pdfmetrics.registerFont(TTFont(font_name, font_path))
            font_registered = font_name
            break
        except Exception:
            continue

    if not font_registered:
        # 最后回退：尝试 reportlab 自带的 CID 中文字体
        try:
            from reportlab.pdfbase.cidfonts import UnicodeCIDFont
            pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
            font_registered = 'STSong-Light'
        except Exception:
            font_registered = 'Helvetica'

    body_font = font_registered
    bold_font = font_registered  # 粗体用同一个（TTF 没有 bold 变体时回退）

    buffer = io.BytesIO()
    doc = SimpleDocTemplate(
        buffer, pagesize=A4,
        leftMargin=2 * cm, rightMargin=2 * cm,
        topMargin=2 * cm, bottomMargin=2 * cm,
    )

    styles = getSampleStyleSheet()
    title_style = ParagraphStyle(
        "CNTitle", parent=styles["Title"],
        fontName=body_font, fontSize=18, alignment=TA_CENTER,
        spaceAfter=12,
    )
    heading_style = ParagraphStyle(
        "CNHeading", parent=styles["Heading2"],
        fontName=body_font, fontSize=14, spaceBefore=12, spaceAfter=6,
    )
    normal_style = ParagraphStyle(
        "CNNormal", parent=styles["Normal"],
        fontName=body_font, fontSize=11, leading=16,
    )
    note_style = ParagraphStyle(
        "CNNote", parent=styles["Normal"],
        fontName=body_font, fontSize=9, leading=13,
        textColor=HexColor("#666666"), leftIndent=20,
    )
    label_style = ParagraphStyle(
        "CNLabel", parent=styles["Normal"],
        fontName=body_font, fontSize=11, leading=16,
    )

    elements = []

    # 标题
    elements.append(Paragraph("电子取证清单", title_style))
    elements.append(Spacer(1, 6))

    # 基本信息表格
    info_data = [
        ["清单标题", checklist.get("title", "")],
        ["业务领域", checklist.get("domain", "")],
        ["案件类型", checklist.get("case_type", "")],
        ["创建时间", checklist.get("created_at", "")],
        ["制作人", user_name],
    ]
    info_table = Table(info_data, colWidths=[80, 380])
    info_table.setStyle(TableStyle([
        ("FONTNAME", (0, 0), (-1, -1), body_font),
        ("FONTSIZE", (0, 0), (-1, -1), 11),
        ("BACKGROUND", (0, 0), (0, -1), HexColor("#F0F2F5")),
        ("FONTSIZE", (0, 0), (0, -1), 11),
        ("GRID", (0, 0), (-1, -1), 0.5, HexColor("#DCDFE6")),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 6),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 6),
        ("LEFTPADDING", (0, 0), (-1, -1), 8),
    ]))
    elements.append(info_table)
    elements.append(Spacer(1, 12))

    # 分组
    groups = [
        ("target", "一、核心取证对象"),
        ("key_data", "二、关键取证数据"),
        ("compliance", "三、法定合规要求"),
        ("custom", "四、自定义取证项目"),
    ]

    for item_type, group_title in groups:
        group_items = [i for i in items_list if i.get("item_type") == item_type]
        if not group_items:
            continue

        elements.append(Paragraph(group_title, heading_style))
        elements.append(HRFlowable(width="100%", thickness=0.5, color=HexColor("#DCDFE6")))

        for item in group_items:
            checkbox = "☑" if item.get("is_checked") else "☐"
            content = item.get("content", "").replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
            elements.append(Paragraph(f"{checkbox}  {content}", normal_style))

            if item.get("user_note"):
                note = item["user_note"].replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
                elements.append(Paragraph(f"备注：{note}", note_style))

        elements.append(Spacer(1, 8))

    # 进度统计
    total = len(items_list)
    checked = sum(1 for i in items_list if i.get("is_checked"))
    elements.append(Spacer(1, 12))
    elements.append(Paragraph(f"完成进度：{checked}/{total}", normal_style))

    # 用户备注
    if checklist.get("notes"):
        notes = checklist["notes"].replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
        elements.append(Paragraph(f"备注：{notes}", normal_style))

    # 签字栏
    elements.append(Spacer(1, 40))
    sign_data = [["制表人签字：____________", "日期：____________"]]
    sign_table = Table(sign_data, colWidths=[240, 240])
    sign_table.setStyle(TableStyle([
        ("FONTNAME", (0, 0), (-1, -1), body_font),
        ("FONTSIZE", (0, 0), (-1, -1), 11),
    ]))
    elements.append(sign_table)

    doc.build(elements)
    buffer.seek(0)
    return buffer


@router.post("/checklists/{checklist_id}/export")
async def export_checklist(
    checklist_id: int,
    request: Request,
    user: dict = Depends(require_login),
    db=Depends(get_db),
):
    """导出取证清单为 Word 文档，保存到本地并用 WPS 打开"""
    import os as _os
    import subprocess as _sp
    from ...core import paths as _paths

    conn, cur = db
    user_id = str(user.get("id", "1"))

    # 获取清单
    await cur.execute(
        "SELECT * FROM evidence_checklists WHERE id = ? AND user_id = ? AND is_deleted = 0",
        (checklist_id, user_id),
    )
    cl = await cur.fetchone()
    if not cl:
        raise HTTPException(status_code=404, detail="清单不存在")

    checklist = dict(cl) if not isinstance(cl, dict) else cl

    # 获取项目
    await cur.execute(
        "SELECT * FROM evidence_checklist_items WHERE checklist_id = ? AND is_deleted = 0 ORDER BY sort_order, id",
        (checklist_id,),
    )
    items = await cur.fetchall()
    items_list = [dict(i) if not isinstance(i, dict) else i for i in items]

    user_name = user.get("real_name", user.get("username", "用户"))
    safe_title = checklist.get("title", str(checklist_id))
    # 清除文件名中的非法字符
    import re as _re
    safe_title = _re.sub(r'[\\/:*?"<>|]', '_', safe_title)

    # 获取导出目录（支持用户自定义路径）
    try:
        from ..admin.config_paths import get_export_save_path
        exports_dir = await get_export_save_path()
    except Exception:
        data_dir = _paths.get_data_dir()
        exports_dir = _os.path.join(data_dir, "exports")
        _os.makedirs(exports_dir, exist_ok=True)

    import time as _time
    timestamp = _time.strftime("%Y%m%d_%H%M%S")
    filename = f"取证清单_{safe_title}_{timestamp}.docx"
    filepath = _os.path.join(exports_dir, filename)

    try:
        buffer = _build_docx_buffer(checklist, items_list, user_name)
        with open(filepath, "wb") as f:
            f.write(buffer.getvalue())
    except ImportError as e:
        raise HTTPException(status_code=500, detail=f"Word组件未安装，无法生成文档: {str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"生成文档失败: {str(e)}")

    # 用 WPS 或系统默认程序打开文档
    _opened = False
    _open_method = ""
    try:
        wps_paths = [
            r"C:\Program Files (x86)\Kingsoft\WPS Office\office6\wps.exe",
            r"C:\Program Files\Kingsoft\WPS Office\office6\wps.exe",
            _os.path.expandvars(r"%LOCALAPPDATA%\Kingsoft\WPS Office\office6\wps.exe"),
        ]
        for wps in wps_paths:
            if _os.path.exists(wps):
                _sp.Popen([wps, filepath], shell=False)
                _opened = True
                _open_method = "WPS"
                break
        if not _opened:
            _os.startfile(filepath)
            _opened = True
            _open_method = "系统默认程序"
    except Exception:
        pass

    return {
        "success": True,
        "data": {
            "filename": filename,
            "filepath": filepath,
            "opened": _opened,
            "open_method": _open_method,
            "message": f"已导出到：{filepath}" + (f"，已用{_open_method}打开" if _opened else ""),
        }
    }
