from typing import List, Literal
from pydantic import BaseModel, Field, field_validator


class Pick(BaseModel):
    numbers: List[int] = Field(min_length=6, max_length=6)
    risk_tag: Literal["안정", "균형", "공격"]
    reason: str = Field(max_length=80)

    @field_validator("numbers")
    @classmethod
    def _check_numbers(cls, v):
        if len(set(v)) != 6:
            raise ValueError("numbers must be 6 unique integers")
        if any(n < 1 or n > 45 for n in v):
            raise ValueError("numbers must be within 1..45")
        return sorted(v)


class TierRationale(BaseModel):
    bonus: str = Field(max_length=40)
    extended: str = Field(max_length=40)
    pool: str = Field(max_length=40)


class Narrative(BaseModel):
    headline: str
    summary_3lines: List[str] = Field(min_length=3, max_length=3)
    hot_cold_comment: str = ""
    warnings: str = ""
    retrospective: str = Field(default="", max_length=80)


class CuratorOutput(BaseModel):
    core_picks: List[Pick]     = Field(min_length=5, max_length=5)
    bonus_picks: List[Pick]    = Field(min_length=5, max_length=5)
    extended_picks: List[Pick] = Field(min_length=5, max_length=5)
    pool_picks: List[Pick]     = Field(min_length=5, max_length=5)
    tier_rationale: TierRationale
    narrative: Narrative
    confidence: int = Field(ge=0, le=100)


def validate_response(data: dict, candidate_numbers: List[List[int]]) -> CuratorOutput:
    out = CuratorOutput.model_validate(data)
    candidate_set = {tuple(sorted(c)) for c in candidate_numbers}
    all_picks = (
        out.core_picks + out.bonus_picks + out.extended_picks + out.pool_picks
    )
    # 중복 픽 검증
    pick_keys = [tuple(p.numbers) for p in all_picks]
    if len(pick_keys) != len(set(pick_keys)):
        raise ValueError("duplicate picks across tiers")
    # 후보에 없는 번호 조합 금지
    for p in all_picks:
        if tuple(p.numbers) not in candidate_set:
            raise ValueError(f"pick {p.numbers} not in candidates")
    return out
