"""document 관련 telemetry — Phase E.2 (analyze_events).

/documents/{id}/analyze 호출을 background task로 DB에 기록.
search_telemetry.py 패턴 동일 (단독 세션 + 에러 흡수).
"""

from __future__ import annotations

import logging
from typing import Any

from sqlalchemy.exc import SQLAlchemyError

from core.database import async_session
from models.analyze_event import AnalyzeEvent

logger = logging.getLogger("document_telemetry")

# source enum validation — 서버 강제 fallback
VALID_SOURCES: set[str] = {
    "document_server",
    "synology_chat",
    "ui_search",
    "ui_detail",
    "eval",
    "unknown",
}
DEFAULT_SOURCE = "document_server"


def sanitize_source(raw: str | None) -> str:
    """source 값 서버 강제. enum 외 값은 unknown, None은 document_server."""
    if raw is None:
        return DEFAULT_SOURCE
    lowered = raw.strip().lower()
    if lowered in VALID_SOURCES:
        return lowered
    return "unknown"


async def record_analyze_event(
    doc_id: int,
    user_id: int | None,
    mode: str,
    text_limit: int | None,
    truncated: bool,
    layers_returned: list[str],
    cached: bool,
    latency_ms: int,
    model_name: str | None,
    prompt_version: str | None,
    error_code: str | None,
    source: str,
    # PR-A shadow observability — 아래 6개는 routing 이 동반될 때만 세팅, 그 외는 None 유지.
    subject_domain: str | None = None,
    risk_flags: list[str] | None = None,
    high_impact_task: bool | None = None,
    escalation_reasons: list[str] | None = None,
    confidence: float | None = None,
    policy_version: str | None = None,
    shadow_would_route_to: str | None = None,
    # PR-B B-1 — 실제 호출 tier 와 R2 backlog guard
    tier: str | None = None,
    escalated_to_26b: bool | None = None,
    suppressed_reason: str | None = None,
    # PR-B B-2 — /ask 3-state answerability
    answerability: str | None = None,
    partial_basis: bool | None = None,
    suggested_query_count: int | None = None,
) -> None:
    """analyze_events INSERT. background task에서 호출 — 에러 삼킴.

    layers_returned: 성공 시 ["evidence","summary"] 등 layer 문자열 리스트. 실패 시 [].
    error_code: None (성공) | "timeout" | "llm" | "parse" | "missing_summary" | "no_text" | "not_found"
    tier: 'triage' | 'primary' | 'fallback' — 실제 호출된 tier (PR-B B-0~B-2).
    suppressed_reason: R2 backlog guard 로 soft escalate 가 suppress 된 경우의 이유 문자열.
    """
    try:
        async with async_session() as session:
            row = AnalyzeEvent(
                doc_id=doc_id,
                user_id=user_id,
                mode=mode,
                text_limit=text_limit,
                truncated=truncated,
                layers_returned=layers_returned,
                cached=cached,
                latency_ms=latency_ms,
                model_name=model_name,
                prompt_version=prompt_version,
                error_code=error_code,
                source=source,
                subject_domain=subject_domain,
                risk_flags=risk_flags,
                high_impact_task=high_impact_task,
                escalated_to_26b=escalated_to_26b,
                escalation_reasons=escalation_reasons,
                confidence=confidence,
                policy_version=policy_version,
                shadow_would_route_to=shadow_would_route_to,
                tier=tier,
                suppressed_reason=suppressed_reason,
                answerability=answerability,
                partial_basis=partial_basis,
                suggested_query_count=suggested_query_count,
            )
            session.add(row)
            await session.commit()
    except SQLAlchemyError as exc:
        logger.warning(f"analyze_event insert failed: {exc}")
