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


# -------------------------
# Validation Block
# -------------------------

class ValidationResult(BaseModel):
    front_back_valid: bool = Field(
        ...,
        description="True if one image is front and the other is back"
    )

    same_card_confidence: Literal["high", "medium", "low"] = Field(
        ...,
        description="Confidence that both images are of the same physical card"
    )

    image_quality: Literal["good", "borderline", "poor"] = Field(
        ...,
        description="Overall image quality assessment"
    )

    damage_override_triggered: bool = Field(
        ...,
        description="True if severe structural damage was detected"
    )


# -------------------------
# Subgrades
# -------------------------

class SubGrades(BaseModel):
    centering: float = Field(..., ge=0, le=10)
    surface: float = Field(..., ge=0, le=10)
    edges: float = Field(..., ge=0, le=10)
    corners: float = Field(..., ge=0, le=10)


# -------------------------
# Defects
# -------------------------

class BBox(BaseModel):
    # normalized bounding box (0–1)
    x: float = Field(..., ge=0.0, le=1.0)
    y: float = Field(..., ge=0.0, le=1.0)
    width: float = Field(..., ge=0.0, le=1.0)
    height: float = Field(..., ge=0.0, le=1.0)


class Defect(BaseModel):
    defect_type: Literal[
        "corner_whitening",
        "edge_whitening",
        "surface_scratch",
        "holo_or_foil_scratching",
        "crease",
        "foil_wear",
        "edge_chip",
        "corner_rounding",
        "staining_or_ink_bleed",
        "post_factory_dents",
        "scuffing"
    ]

    severity: Literal["minimal", "moderate", "major"]

    confidence: float = Field(
        ...,
        ge=0.0,
        le=1.0,
        description="Model confidence in this defect detection"
    )

    location_zone: Literal[
        "front_top_left_corner",
        "front_top_right_corner",
        "front_bottom_left_corner",
        "front_bottom_right_corner",
        "front_top_edge_left",
        "front_top_edge_center",
        "front_top_edge_right",
        "front_bottom_edge_left",
        "front_bottom_edge_center",
        "front_bottom_edge_right",
        "front_left_edge_upper",
        "front_left_edge_center",
        "front_left_edge_lower",
        "front_right_edge_upper",
        "front_right_edge_center",
        "front_right_edge_lower",
        "front_inner_top_left",
        "front_inner_top_center",
        "front_inner_top_right",
        "front_inner_middle_left",
        "front_inner_middle_center",
        "front_inner_middle_right",
        "front_inner_bottom_left",
        "front_inner_bottom_center",
        "front_inner_bottom_right"
    ]

    bbox_norm: BBox
    notes: str


class DefectMap(BaseModel):
    front: List[Defect]
    back: List[Defect]


# -------------------------
# Final Grading Result
# -------------------------

class GradingResult(BaseModel):
    validation: ValidationResult

    overall_grade: float = Field(
        ...,
        ge=1.0,
        le=10.0,
        description="Final overall grade after all rules applied"
    )

    front_subgrades: SubGrades
    back_subgrades: SubGrades

    environment_score: int = Field(
        ...,
        ge=0,
        le=100,
        description="Primary image reliability score"
    )

    accuracy_score: int = Field(
        ...,
        ge=0,
        le=100,
        description="Secondary grading confidence score"
    )

    grading_rationale: str = Field(
        ...,
        min_length=5,
        description="Collector-facing explanation of the grade"
    )

    defect_map: DefectMap
