"""渲染编排：查企业/订单 → 合并取值 → 渲染 → 转 PDF → 组装响应。"""
from __future__ import annotations

from datetime import datetime
from pathlib import Path

from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.logger import get_logger
from app.core.paths import safe_filename, safe_join
from app.core.response import AppError
from app.repositories.common_enterprise import get_enterprise
from app.repositories.order import get_order
from app.schemas.common import RenderRequest
from app.services.converter import convert_to_pdf
from app.services.cos_storage import upload_file
from app.services.document import render_word
from app.services.engine import render_template

logger = get_logger(__name__)


def render(req: RenderRequest, session: Session) -> dict:
    """渲染模板：按企业/订单取信息、渲染、可选转 PDF，返回响应 data dict（不写 render_record）。"""
    # 1. 企业信息
    enterprise = None
    if req.enterprise_id is not None:
        enterprise = get_enterprise(session, req.enterprise_id)
        if enterprise is None:
            raise AppError(f"企业信息不存在: id={req.enterprise_id}", code=404, status_code=404)

    # 2. 订单信息
    order = None
    categories: dict = {}
    if req.order_id is not None:
        order = get_order(session, req.order_id)
        if order is None:
            raise AppError(f"订单不存在: id={req.order_id}", code=404, status_code=404)
        categories = order.categories or {}
        # 未显式传企业时，自动使用订单关联的企业
        if enterprise is None and order.enterprise_id is not None:
            enterprise = get_enterprise(session, order.enterprise_id)
            if enterprise is None:
                raise AppError(f"订单关联的企业不存在: id={order.enterprise_id}", code=404, status_code=404)

    values = dict(req.values or {})
    if enterprise is not None:
        base = enterprise.to_template_values()
        base.update(values)
        values = base

    # 3. 解析模板与输出路径
    template_path = safe_join(Path(settings.template_dir), req.template)
    if not template_path.exists():
        raise AppError(f"模板不存在: {req.template}", code=404, status_code=404)

    if req.output_name:
        output_name = req.output_name
    elif enterprise is not None and enterprise.name_en:
        output_name = f"{safe_filename(enterprise.name_en)}_{template_path.stem}{template_path.suffix}"
    else:
        stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_name = f"{template_path.stem}_{stamp}{template_path.suffix}"

    output_path = safe_join(Path(settings.output_dir), output_name)

    logger.info("渲染模板 %s -> %s", req.template, output_name)

    # 4. 渲染（docx 走 render_word，其余走分发器）
    if template_path.suffix.lower() == ".docx":
        weee = categories if (categories and "WEEE" in req.template) else None
        result = render_word(template_path, values, output_path, to_pdf=req.to_pdf, categories=weee)
        pdf_path = result.get("pdf_path")
        pdf_name = result.get("pdf_name")
    else:
        result = render_template(template_path, values, output_path)
        pdf_name = None
        pdf_path = None
        # 将替换后的文件转换为 PDF（仅 xlsx）
        if req.to_pdf and result.get("type") == "xlsx":
            pdf_name = f"{Path(output_name).stem}.pdf"
            pdf_path = convert_to_pdf(output_path, safe_join(Path(settings.output_dir), pdf_name))

    # 5. 组装响应
    result["enterprise_id"] = enterprise.id if enterprise is not None else None
    result["order_id"] = req.order_id
    result["order_no"] = order.order_no if order is not None else None
    result["template"] = req.template
    result["output_name"] = output_name
    result["pdf_name"] = pdf_name
    result["pdf_path"] = str(pdf_path) if pdf_path else None
    result["download_url"] = f"/api/template/download/{output_name}"
    result["pdf_download_url"] = f"/api/template/download/{pdf_name}" if pdf_name else None

    # 6. 上传生成文件到 COS（仅配置了 COS 才上传）
    result["output_url"] = None
    result["pdf_url"] = None
    if settings.cos_bucket:
        result["output_url"] = upload_file(output_path)
        if pdf_path:
            result["pdf_url"] = upload_file(pdf_path)

    # 7. 回写 SaaS（待补充：语句由用户填写，暂注释）
    # TODO: 回写 SaaS
    # saas.write_back(...)  # 语句留空，由用户补充

    return result
