"""下载企业附件图片/PDF 并 OCR，打印到控制台，收集识别结果/问题（后续回写 SaaS）。

用法（在 code 目录下）：
    python -m app.scripts.ocr_enterprise <企业代码>
"""
from __future__ import annotations

import sys
from pathlib import Path

from app.core.config import settings
from app.core.database import SourceSessionLocal
from app.core.download import download_file
from app.core.image import pdf_to_images
from app.core.paths import safe_filename
from app.core.response import AppError
from app.repositories.nl_enterprise import get_enterprise_detail
from app.services.biz_license_parser import parse_biz_license
from app.services.tencent_ocr import recognize_general_accurate, recognize_idcard, recognize_passport

IDCARD_LABELS = {
    "name": "姓名", "sex": "性别", "nation": "民族", "birth": "出生",
    "address": "住址", "id_num": "身份证号", "authority": "签发机关", "valid_date": "有效期限",
}
PASS_LABELS = {
    "passport_no": "护照号码", "name": "姓名", "nationality": "国籍", "sex": "性别",
    "date_of_birth": "出生日期", "date_of_expiration": "有效期至", "issue_authority": "签发机关",
}
BIZ_LABELS = {
    "reg_num": "注册号", "name": "公司名称", "address": "地址", "person": "法定代表人",
}


def _print_fields(title: str, data: dict, labels: dict) -> None:
    print(f"\n=== {title} ===")
    found = False
    for key, label in labels.items():
        value = data.get(key)
        if value:
            print(f"  {label}: {value}")
            found = True
    if not found:
        print("  (无识别结果)")


def _print_raw(title: str, lines: list[str]) -> None:
    print(f"\n=== {title} ===\n  --- OCR 全文 ---")
    for text in lines:
        print(" ", text)


def _resolve_side(name: str) -> str | None:
    if "正" in name:
        return "FRONT"
    if "反" in name:
        return "BACK"
    return None


def _classify(name: str) -> str:
    if "营业执照" in name or "business" in name.lower() or "license" in name.lower():
        return "business"
    if "护照" in name or "passport" in name.lower():
        return "passport"
    return "idcard"


def run(code: str) -> list[dict]:
    """下载并 OCR 企业附件，返回每条文件的结果（含识别失败），供后续回写 SaaS。"""
    # Windows 控制台默认 GBK，强制 UTF-8 避免中文乱码
    try:
        sys.stdout.reconfigure(encoding="utf-8")
    except Exception:
        pass

    with SourceSessionLocal() as session:
        rows = get_enterprise_detail(session, code)
    if not rows:
        print("未找到企业或附件")
        return []

    enterprise_name = safe_filename(rows[0]["NameEng"] or "")
    print("企业:", rows[0]["NameEng"])
    out_dir = Path(settings.output_dir) / "downloads"

    records: list[dict] = []
    for r in rows:
        name = r["F_FileName"]
        url = r["F_FilePath"]
        ftype = (r["F_FileType"] or "").lower()
        if not url:
            continue

        prefix = f"{enterprise_name}_" if enterprise_name else ""
        local = out_dir / f"{prefix}{name}"
        download_file(url, local)

        kind = _classify(name)
        record = {"file_name": name, "doc_type": kind, "status": "success", "error": None, "fields": None}

        try:
            if kind == "business":
                # 营业执照可能是 PDF（多页逐页 OCR）或图片
                images = pdf_to_images(local) if ftype == "pdf" else [local]
                lines = []
                for image in images:
                    lines.extend(recognize_general_accurate(image))
                _print_raw(name, lines)
                fields = parse_biz_license(lines)
                _print_fields("解析字段", fields, BIZ_LABELS)
                record["fields"] = fields
            elif kind == "passport":
                fields = recognize_passport(local)
                _print_fields(name, fields, PASS_LABELS)
                record["fields"] = fields
            else:
                fields = recognize_idcard(local, _resolve_side(name))
                _print_fields(name, fields, IDCARD_LABELS)
                record["fields"] = fields
        except AppError as exc:
            record["error"] = str(exc)
            record["status"] = "failed"
            # 专用识别（身份证/护照）失败时，回退通用 OCR 至少拿原始文字
            if kind in ("passport", "idcard"):
                try:
                    lines = recognize_general_accurate(local)
                    _print_raw(f"{name}（专用识别失败，回退通用 OCR）", lines)
                    record["status"] = "fallback"
                    record["fields"] = {"raw_text": lines}
                except AppError as exc2:
                    print(f"\n=== {name} ===\n  识别失败: {exc2}")
                    record["error"] = str(exc2)
            else:
                print(f"\n=== {name} ===\n  识别失败: {exc}")

        records.append(record)

    # 汇总识别问题（后续回写 SaaS）
    print("\n===== 识别结果汇总 =====")
    problems = [rec for rec in records if rec["status"] != "success"]
    if problems:
        for rec in problems:
            print(f"  [{rec['status']}] {rec['doc_type']} {rec['file_name']}: {rec['error']}")
    else:
        print("  全部识别成功")

    return records


if __name__ == "__main__":
    run(sys.argv[1] if len(sys.argv) > 1 else "")
