# AI_CHANGELOG
# - 2026-03-29 | Prompt: DWS_TASK_ENGINE ETL 任务 | 新建文件。
#   提供 POST /api/internal/run-job 端点，供 ETL 按 job_name 执行
#   biz.trigger_jobs 中的任务。Internal-Token 认证。

# -*- coding: utf-8 -*-
"""
内部任务执行 API — ETL/内部服务调用入口。

端点：
- POST /api/internal/run-job — 按 job_name 执行 biz.trigger_jobs 中的任务

认证方式：Authorization: Internal-Token {token}
"""

from __future__ import annotations

import logging

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, Field

from app.auth.internal_token import verify_internal_token

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/internal", tags=["internal-events"])


class RunJobByNameRequest(BaseModel):
    """按 job_name 执行任务的请求体。"""
    job_name: str = Field(..., description="任务名称，如 recall_completion_check")


class RunJobByNameResponse(BaseModel):
    """执行结果。"""
    success: bool
    message: str
    job_name: str


class EtlCompletedRequest(BaseModel):
    """ETL 完成通知请求体。"""
    pipeline: str = Field(default="api_full", description="完成的 pipeline 名称")
    site_id: int | None = Field(default=None, description="门店 ID（可选）")


class EtlCompletedResponse(BaseModel):
    """ETL 完成编排结果。"""
    success: bool
    recall_result: dict | None = None
    task_gen_result: dict | None = None
    message: str = ""


@router.post("/etl-completed", response_model=EtlCompletedResponse)
async def etl_completed_endpoint(
    body: EtlCompletedRequest,
    _token: str = Depends(verify_internal_token),
) -> EtlCompletedResponse:
    """ETL pipeline 完成后的统一编排入口。

    CHANGE 2026-04-07 | Fix-12：ETL 完成后自动触发。
    编排顺序：recall_detector.run() → task_generator.run()
    """
    from app.services import recall_detector, task_generator

    recall_result = None
    task_gen_result = None
    errors = []

    # Step 1: 先检查召回完成（含回溯）
    try:
        recall_result = recall_detector.run()
        logger.info("ETL 编排 Step1 recall_detector 完成: %s", recall_result)
    except Exception:
        logger.exception("ETL 编排 Step1 recall_detector 失败")
        errors.append("recall_detector failed")

    # Step 2: 再生成新任务
    try:
        task_gen_result = task_generator.run()
        logger.info("ETL 编排 Step2 task_generator 完成: %s", task_gen_result)
    except Exception:
        logger.exception("ETL 编排 Step2 task_generator 失败")
        errors.append("task_generator failed")

    # Step 3: 触发 AI 财务洞察预生成（App2 × 8 时间维度）
    # 若请求未带 site_id，查询所有 active site 逐个触发
    try:
        from app.services.trigger_scheduler import fire_event

        site_ids: list[int] = []
        if body.site_id is not None:
            site_ids = [body.site_id]
        else:
            from app.database import get_connection as _gc
            _c = _gc()
            try:
                with _c.cursor() as _cur:
                    _cur.execute("SELECT DISTINCT site_id FROM biz.trigger_jobs WHERE site_id IS NOT NULL")
                    site_ids = [r[0] for r in _cur.fetchall()]
                _c.commit()
            finally:
                _c.close()

        for sid in site_ids:
            try:
                fire_event("ai_dws_completed", {"site_id": sid})
            except Exception:
                logger.exception("触发 ai_dws_completed 失败: site_id=%s", sid)
    except Exception:
        logger.exception("ai_dws_completed 事件批量触发失败")

    success = len(errors) == 0
    return EtlCompletedResponse(
        success=success,
        recall_result=recall_result,
        task_gen_result=task_gen_result,
        message="; ".join(errors) if errors else "ok",
    )


@router.post("/run-job", response_model=RunJobByNameResponse)
async def run_job_by_name_endpoint(
    body: RunJobByNameRequest,
    _token: str = Depends(verify_internal_token),
) -> RunJobByNameResponse:
    """按 job_name 查找并执行 biz.trigger_jobs 中的任务。

    ETL DWS_TASK_ENGINE 任务通过此端点按顺序执行后端任务引擎的各个步骤。
    """
    from app.database import get_connection
    from app.services.trigger_scheduler import run_job_by_id

    conn = get_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT id FROM biz.trigger_jobs WHERE job_name = %s",
                (body.job_name,),
            )
            row = cur.fetchone()
        conn.commit()
    finally:
        conn.close()

    if not row:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"任务 '{body.job_name}' 不存在",
        )

    job_id = row[0]
    result = run_job_by_id(job_id)

    logger.info(
        "内部任务执行: job_name=%s, success=%s",
        body.job_name, result.get("success"),
    )
    return RunJobByNameResponse(
        success=result.get("success", False),
        message=result.get("message", ""),
        job_name=body.job_name,
    )
