"""法国(FR)企业文档生成编排：N 模板 → N 文件，各自上传回写。"""
from __future__ import annotations

import shutil
import traceback
import uuid
from pathlib import Path

from app.core.config import settings
from app.core.countries import find_templates
from app.core.logger import get_logger
from app.core.paths import safe_filename
from app.core.response import AppError
from app.repositories.epr_generate_log import insert_epr_generate_log
from app.repositories.fr_enterprise import FR_TEMPLATE_CONFIG, update_epr_push_status
from app.services.cos_storage import upload_file
from app.services.enterprise_document import (
    PHOTO_ROTATION,
    _build_values,
    _ocr_idcard_fields,
    _prepare_images,
    _write_back_annex,
    _write_back_status,
    render_templates,
)

logger = get_logger(__name__)

# 日志级别权重：合并多条步骤日志时取最高级别
_LEVEL_ORDER = {"info": 0, "warning": 1, "error": 2}


def generate_fr_documents(record: dict, files: list[dict], gen_file_prefix="", gen_file_suffix="") -> dict:
    """FR 文档生成：N 模板 → N 文件，各自上传回写（文件名/分类按模板名 key 取 FR_TEMPLATE_CONFIG）。"""
    steps: list[dict] = []

    def _record(name: str, status: str, **kw) -> None:
        steps.append({"step": name, "status": status, **kw})

    vat_reg_info_id = record.get("VATRegInfoID")
    country_code = record.get("Country")
    code = record.get("Code")
    enterprise_name = record.get("NameEng")
    batch_id = str(uuid.uuid4())

    message_lines: list[str] = []
    detail_lines: list[str] = []
    final_level = "info"

    def _log(step: str, level: str, message: str | None = None, detail: str | None = None) -> None:
        nonlocal final_level
        if _LEVEL_ORDER.get(level, 0) > _LEVEL_ORDER.get(final_level, 0):
            final_level = level
        if message:
            message_lines.append(f"[{level}] {step}: {message}")
        else:
            message_lines.append(f"[{level}] {step}")
        if detail:
            detail_lines.append(detail)

    def _flush() -> None:
        insert_epr_generate_log(
            batch_id=batch_id, code=code, vat_reg_info_id=vat_reg_info_id,
            enterprise_name=enterprise_name, country=country_code,
            level=final_level,
            message="\n".join(message_lines) or None,
            detail="\n\n".join(detail_lines) or None,
        )

    _log("入口", "info", f"code={code} name={enterprise_name} country={country_code}")

    if not country_code:
        logger.warning("无法识别国家: %s", record.get("Country"))
        _log("确定国家", "error", f"无法识别国家: {record.get('Country')}")
        _record("确定国家", "failed", error=f"无法识别国家: {record.get('Country')}")
        _flush()
        return {"status": "failed", "steps": steps}
    _record("确定国家", "success", country=country_code)

    templates = find_templates(country_code)
    if not templates:
        logger.warning("国家 %s 无模板", country_code)
        _log("查找模板", "error", f"国家 {country_code} 无模板")
        _record("查找模板", "failed", error=f"国家 {country_code} 无模板")
        _flush()
        return {"status": "failed", "steps": steps}
    logger.info("找到 %d 个模板", len(templates))
    _log("查找模板", "info", f"国家 {country_code} 找到 {len(templates)} 个模板")
    _record("查找模板", "success", count=len(templates))

    try:
        values = _build_values(record)
        enterprise_name_safe = safe_filename(enterprise_name or "out")
        out_dir = Path(settings.output_dir) / "generate" / enterprise_name_safe
        out_dir.mkdir(parents=True, exist_ok=True)

        images, image_errors = _prepare_images(files, out_dir)
        if image_errors:
            _log("下载附件", "error", "; ".join(m for m, _ in image_errors), "\n\n".join(d for _, d in image_errors if d))

        ocr, ocr_errors = _ocr_idcard_fields(images.get("身份证"), PHOTO_ROTATION.get("身份证", 0))
        if ocr_errors:
            _log("OCR", "warning", "; ".join(m for m, _ in ocr_errors), "\n\n".join(d for _, d in ocr_errors))
        if ocr.get("法人性别"):
            values["法人性别"] = ocr["法人性别"]
        if not values.get("签发城市") and ocr.get("签发城市"):
            values["签发城市"] = ocr["签发城市"]

        pdf_paths, _, render_errors = render_templates(templates, values, images, out_dir)
        if render_errors:
            _log("渲染模板", "error", "; ".join(m for m, _ in render_errors), "\n\n".join(d for _, d in render_errors if d))
        _record("渲染模板", "success", count=len(templates))
        if not pdf_paths:
            raise AppError("所有模板渲染失败，无可用 PDF")

        # N 文件：每个模板一个文件，各自上传 + 回写（按源文件后缀区分格式：PDF/Excel 分别上传）
        oss_url = None
        for src in pdf_paths:
            cfg = FR_TEMPLATE_CONFIG[src.stem]  # 模板名只当 key
            ext = src.suffix.lower()  # 保留源格式：.pdf / .xlsx / .xlsm
            out_file = out_dir / f"{gen_file_prefix}{enterprise_name_safe}_{cfg['name']}{gen_file_suffix}{ext}"
            if out_file != src:
                shutil.copyfile(src, out_file)
            url = upload_file(out_file) if settings.cos_bucket else None
            logger.info("生成文件 -> %s", out_file)
            _log("生成文件", "info", f"{out_file} -> {url}")
            _record("生成文件", "success", path=str(out_file), url=url)
            if url:
                _write_back_annex(vat_reg_info_id, out_file, url, log=_log, file_category_id=cfg['category'])
            if oss_url is None:
                oss_url = url

        _write_back_status(vat_reg_info_id, 6, update_epr_push_status, log=_log)

        _log("生成文档", "info", "success")
        _flush()
        return {"status": "success", "oss_url": oss_url, "merged": str(pdf_paths[0]), "steps": steps}
    except Exception as exc:  # noqa: BLE001
        logger.exception("生成文档失败: %s", exc)
        _log("生成文档", "error", str(exc), traceback.format_exc())
        _record("生成文档", "failed", error=str(exc))
        _write_back_status(vat_reg_info_id, 7, update_epr_push_status, str(exc), log=_log)
        _flush()
        return {"status": "failed", "error": str(exc), "steps": steps}
