"""文档生成 job（轮询进程）。

正常：python -m app.jobs.generate_documents_job（每分钟轮询，空结果休眠 10 分钟）
测试：python -m app.jobs.generate_documents_job --once（执行一轮后退出）
"""
from __future__ import annotations

import sys
import time

from app.core.config import settings
from app.core.database import SourceSessionLocal
from app.core.logger import get_logger
from app.repositories.nl_enterprise import get_annex_files, get_schedule_recode, update_vat_push_status
from app.services.nl_document import generate_nl_documents

logger = get_logger(__name__)


def _mark_failed(vat_reg_info_id, error: str) -> None:
    """回写失败状态 -1；回写失败仅记日志，不阻断。"""
    if not vat_reg_info_id:
        return
    try:
        with SourceSessionLocal() as session:
            update_vat_push_status(session, vat_reg_info_id, -1, error)
    except Exception as exc:  # noqa: BLE001
        logger.error("回写失败状态失败: %s", exc)


def _process_record(record: dict) -> None:
    """处理单条待推送记录：取附件 → 生成文档；无附件或失败则标记 -1。"""
    code = record.get("Code")
    vat_reg_info_id = record.get("VATRegInfoID")
    logger.info("开始处理 code=%s", code)
    try:
        with SourceSessionLocal() as session:
            files = get_annex_files(session, code)
        if not files:
            logger.warning("记录无附件 code=%s，标记失败", code)
            _mark_failed(vat_reg_info_id, "无附件文件")
            return

        result = generate_nl_documents(
            record, files,
            gen_file_prefix="",
            gen_file_suffix="",
        )
        logger.info("生成结果 code=%s -> %s", code, result.get("status"))
        if result.get("status") != "success":
            _mark_failed(vat_reg_info_id, result.get("error") or "生成失败")
    except Exception as exc:  # noqa: BLE001
        logger.exception("处理记录失败 code=%s: %s", code, exc)
        _mark_failed(vat_reg_info_id, str(exc))


def _run_round() -> bool:
    """执行一轮：查询待推送记录并逐条处理；返回是否存在记录（有=True）。"""
    with SourceSessionLocal() as session:
        records = get_schedule_recode(session)
    if not records:
        logger.info("无待推送记录")
        return False
    logger.info("本次待推送记录 %d 条", len(records))
    for record in records:
        _process_record(record)
    return True


def run_once() -> None:
    """执行一轮后退出（测试用 --once）。"""
    _run_round()


def run() -> None:
    """轮询循环：有记录处理完休眠 job_poll_seconds 秒，空结果休眠 job_empty_sleep_seconds 秒。"""
    while True:
        try:
            has_records = _run_round()
            sleep_seconds = settings.job_poll_seconds if has_records else settings.job_empty_sleep_seconds
            logger.info("休眠 %s 秒", sleep_seconds)
            time.sleep(sleep_seconds)
        except Exception as exc:  # noqa: BLE001
            logger.exception("job 循环异常: %s", exc)
            time.sleep(settings.job_empty_sleep_seconds)


if __name__ == "__main__":
    if "--once" in sys.argv:
        run_once()
    else:
        run()
