"""SP-4 — Windows insta-render → NAS internal webhook.

POST /api/internal/insta/update
- X-Internal-Key 인증 필수
- task DB row update (status, progress, result_path, error)
- result_path는 nginx 서빙 경로 (예: /media/insta/{slate_id}/01.png)
- succeeded 시 params에서 slate_id 추출 → result_id 세팅
"""
from __future__ import annotations

import json
import logging
import os
from typing import Optional

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

from . import config, db
from .auth import verify_internal_key

logger = logging.getLogger(__name__)
router = APIRouter()


def _register_rendered_assets(slate_id: int) -> int:
    """워커가 저장한 10장 PNG를 card_assets로 등록.

    cutover(2026-05-19) 후 렌더는 Windows insta-render 워커가 NAS SMB 볼륨에
    직접 쓰지만, NAS DB에 card_assets를 등록하는 단계가 누락됐었다. 이 함수가
    그 갭을 메운다. 워커 출력 경로 후보를 순서대로 스캔해 실제 파일만 등록한다
    (경로 정합 가드: CARDS_DIR 하위 / INSTA_DATA_PATH 직하 둘 다 수용).

    저장하는 file_path는 insta-lab 컨테이너 내부 절대경로 →
    get_asset(FileResponse) / package(zip)가 그대로 읽는다.
    """
    candidates = [
        os.path.join(config.CARDS_DIR, str(slate_id)),       # /app/data/insta_cards/{id}
        os.path.join(config.INSTA_DATA_PATH, str(slate_id)),  # /app/data/{id}
    ]
    for base in candidates:
        if not os.path.isdir(base):
            continue
        count = 0
        for page in range(1, 11):
            fp = os.path.join(base, f"{page:02d}.png")
            if os.path.exists(fp) and os.path.getsize(fp) > 0:
                db.add_card_asset(slate_id, page, fp)
                count += 1
        if count:
            logger.info("card_assets 등록: slate=%s pages=%d dir=%s", slate_id, count, base)
            return count
    logger.warning("렌더 PNG를 찾지 못함: slate=%s (후보=%s)", slate_id, candidates)
    return 0


class UpdatePayload(BaseModel):
    task_id: str
    status: str = Field(..., description="processing|succeeded|failed")
    progress: int = Field(..., ge=0, le=100)
    result_path: Optional[str] = None
    error: Optional[str] = None


@router.post(
    "/api/internal/insta/update",
    dependencies=[Depends(verify_internal_key)],
)
def insta_update(payload: UpdatePayload):
    task = db.get_task(payload.task_id)
    if task is None:
        raise HTTPException(404, f"task not found: {payload.task_id}")

    result_id = None
    if payload.status == "succeeded":
        try:
            # DB stores params (not input_data) from create_task
            params_data = json.loads(task.get("params") or "{}")
            result_id = params_data.get("slate_id")
        except (ValueError, TypeError):
            pass

    db.update_task(
        payload.task_id,
        payload.status,
        payload.progress,
        message=payload.result_path or "",
        result_id=result_id,
        error=payload.error,
    )
    # succeeded 시 slate_status도 'rendered'로 갱신 + card_assets 등록 (cutover 후 NAS가 처리)
    if payload.status == "succeeded" and result_id is not None:
        try:
            db.update_slate_status(result_id, "rendered")
        except Exception:
            logger.exception("update_slate_status %s 실패 (무시)", result_id)
        try:
            _register_rendered_assets(result_id)
        except Exception:
            logger.exception("card_assets 등록 %s 실패 (무시)", result_id)
    logger.info(
        "internal/insta/update task=%s status=%s progress=%d",
        payload.task_id, payload.status, payload.progress,
    )
    return {"ok": True}
