"""study_quiz_session_jobs ORM (Phase 4-B v1) — 세션 단위 분석 작업 큐.

study_question_jobs 와 분리 — FK 단일 의미 (study_quiz_session_id NOT NULL)
+ 운영 SQL 명확성 + 4-A/4-B 가드/재시도 정책 차이.

terminal status (completed/failed/skipped) 는 completed_at 항상 기록.
재시도는 기존 row 를 pending 으로 되살리지 않고 새 row 생성 — 이력 누적.
v1 은 단일 작업 종류 ('analysis') 라 kind 컬럼 없이 session_id 만 키.
"""

from __future__ import annotations

from datetime import datetime
from typing import Any

from sqlalchemy import BigInteger, DateTime, ForeignKey, SmallInteger, String, Text, text
from sqlalchemy.dialects.postgresql import JSONB, insert as pg_insert
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Mapped, mapped_column

from core.database import Base


class StudyQuizSessionJob(Base):
    __tablename__ = "study_quiz_session_jobs"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
    study_quiz_session_id: Mapped[int] = mapped_column(
        BigInteger,
        ForeignKey("study_quiz_sessions.id", ondelete="CASCADE"),
        nullable=False,
    )
    user_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
    )
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="pending")
    attempts: Mapped[int] = mapped_column(SmallInteger, nullable=False, default=0)
    max_attempts: Mapped[int] = mapped_column(SmallInteger, nullable=False, default=2)
    error_code: Mapped[str | None] = mapped_column(String(40))
    error_message: Mapped[str | None] = mapped_column(Text)
    payload: Mapped[dict | None] = mapped_column(JSONB)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=datetime.now, nullable=False
    )
    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))


async def enqueue_session_analysis_job(
    session: AsyncSession,
    *,
    study_quiz_session_id: int,
    user_id: int,
    payload: dict[str, Any] | None = None,
) -> bool:
    """study_quiz_session_jobs 에 row 추가 (DB 레벨 중복 방어).

    같은 session_id 의 활성 행 (pending/processing) 이 이미 있으면 False 반환.
    terminal 이력은 별도 row 로 누적되므로 이번 호출이 failed/skipped/completed row 와
    무관하게 새 active 행을 만들 수 있다.

    Returns: True = 새 enqueue 발생, False = 중복으로 건너뜀.
    """
    values: dict[str, Any] = {
        "study_quiz_session_id": study_quiz_session_id,
        "user_id": user_id,
        "status": "pending",
    }
    if payload is not None:
        values["payload"] = payload
    stmt = (
        pg_insert(StudyQuizSessionJob)
        .values(**values)
        .on_conflict_do_nothing(
            index_elements=["study_quiz_session_id"],
            index_where=text("status IN ('pending', 'processing')"),
        )
    )
    result = await session.execute(stmt)
    return result.rowcount > 0
