from __future__ import annotations
from typing import List, Optional
from uuid import UUID
from datetime import datetime
from decimal import Decimal
from pydantic import BaseModel, EmailStr, field_validator


# ── Auth ──────────────────────────────────────────────────────────────────────

class Token(BaseModel):
    access_token: str
    token_type: str = "bearer"
    user_type: str                   # "student" | "admin"


class TokenData(BaseModel):
    sub: str
    user_type: str


# ── User (student) ────────────────────────────────────────────────────────────

class UserRegister(BaseModel):
    email: EmailStr
    password: str
    first_name: str
    last_name: str
    grade: Optional[int] = None      # 8 or 12
    school: Optional[str] = None
    city: Optional[str] = None
    county: Optional[str] = None

    @field_validator("password")
    @classmethod
    def password_strength(cls, v: str) -> str:
        if len(v) < 6:
            raise ValueError("Parola trebuie să aibă cel puțin 6 caractere")
        return v


class UserLogin(BaseModel):
    email: EmailStr
    password: str


class UserUpdate(BaseModel):
    email: Optional[EmailStr] = None
    password: Optional[str] = None
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    grade: Optional[int] = None
    school: Optional[str] = None
    city: Optional[str] = None
    county: Optional[str] = None
    is_active: Optional[bool] = None

    @field_validator("password")
    @classmethod
    def password_strength(cls, v):
        if v is not None and len(v) < 6:
            raise ValueError("Parola trebuie să aibă cel puțin 6 caractere")
        return v


class UserAdminCreate(BaseModel):
    email: EmailStr
    password: str
    first_name: str
    last_name: str
    grade: Optional[int] = None
    school: Optional[str] = None
    city: Optional[str] = None
    county: Optional[str] = None
    is_active: bool = True

    @field_validator("password")
    @classmethod
    def password_strength(cls, v: str) -> str:
        if len(v) < 6:
            raise ValueError("Parola trebuie să aibă cel puțin 6 caractere")
        return v


class UserResponse(BaseModel):
    id: UUID
    email: str
    first_name: str
    last_name: str
    grade: Optional[int]
    school: Optional[str]
    city: Optional[str]
    county: Optional[str]
    is_active: bool
    created_at: datetime

    model_config = {"from_attributes": True}


# ── Admin ─────────────────────────────────────────────────────────────────────

class AdminLogin(BaseModel):
    email: EmailStr
    password: str


class AdminCreate(BaseModel):
    email: EmailStr
    password: str
    first_name: str
    last_name: str
    role: str = "admin"


class AdminResponse(BaseModel):
    id: UUID
    email: str
    first_name: str
    last_name: str
    role: str
    is_active: bool
    created_at: datetime

    model_config = {"from_attributes": True}


# ── Exam types & subjects ─────────────────────────────────────────────────────

class ExamTypeResponse(BaseModel):
    id: int
    code: str
    name: str
    description: Optional[str]
    grade_level: Optional[int]

    model_config = {"from_attributes": True}


class SubjectResponse(BaseModel):
    id: int
    name: str
    code: str
    exam_type_id: int
    is_mandatory: bool
    profile: Optional[str]

    model_config = {"from_attributes": True}


# ── Questions ─────────────────────────────────────────────────────────────────

class OptionCreate(BaseModel):
    option_label: str
    option_text: str
    is_correct: bool


class OptionUpdate(BaseModel):
    option_label: Optional[str] = None
    option_text: Optional[str] = None
    is_correct: Optional[bool] = None


class OptionResponse(BaseModel):
    id: UUID
    option_label: str
    option_text: str

    model_config = {"from_attributes": True}


class OptionWithCorrect(OptionResponse):
    """Used in admin views and result displays."""
    is_correct: bool


class QuestionCreate(BaseModel):
    question_type: str = "multiple_choice"
    question_text: str
    points: float = 10.0
    order_index: int
    options: List[OptionCreate] = []


class QuestionUpdate(BaseModel):
    question_type: Optional[str] = None
    question_text: Optional[str] = None
    points: Optional[float] = None
    order_index: Optional[int] = None


class QuestionResponse(BaseModel):
    id: UUID
    question_number: int
    question_type: str
    question_text: str
    points: Decimal
    order_index: int
    options: List[OptionResponse]

    model_config = {"from_attributes": True}


class QuestionAdminResponse(QuestionResponse):
    """Admin version includes correct flags."""
    options: List[OptionWithCorrect]  # type: ignore[assignment]


# ── Exams ─────────────────────────────────────────────────────────────────────

class ExamCreate(BaseModel):
    title: str
    subject_id: int
    exam_type_id: int
    year: Optional[int] = None
    duration_minutes: int = 120
    total_points: int = 100
    instructions: Optional[str] = None


class ExamUpdate(BaseModel):
    title: Optional[str] = None
    year: Optional[int] = None
    duration_minutes: Optional[int] = None
    total_points: Optional[int] = None
    instructions: Optional[str] = None
    is_published: Optional[bool] = None


class ExamSummary(BaseModel):
    id: UUID
    title: str
    subject: SubjectResponse
    exam_type: ExamTypeResponse
    year: Optional[int]
    duration_minutes: int
    total_points: int
    question_count: int
    is_published: bool

    model_config = {"from_attributes": True}


class ExamDetail(BaseModel):
    id: UUID
    title: str
    subject: SubjectResponse
    exam_type: ExamTypeResponse
    year: Optional[int]
    duration_minutes: int
    total_points: int
    instructions: Optional[str]
    questions: List[QuestionResponse]

    model_config = {"from_attributes": True}


class ExamAdminDetail(ExamDetail):
    is_published: bool
    created_at: datetime
    questions: List[QuestionAdminResponse]  # type: ignore[assignment]


# ── Sessions ──────────────────────────────────────────────────────────────────

class StartSession(BaseModel):
    exam_id: UUID


class SaveAnswer(BaseModel):
    selected_option_id: Optional[UUID] = None
    answer_text: Optional[str] = None


class SessionSummary(BaseModel):
    id: UUID
    exam_id: UUID
    exam_title: str
    subject_name: str
    exam_type_code: str
    started_at: datetime
    submitted_at: Optional[datetime]
    status: str
    total_score: Optional[Decimal]
    total_points: Optional[int]
    grade: Optional[Decimal]
    passed: Optional[bool]

    model_config = {"from_attributes": True}


class AnswerResult(BaseModel):
    question_id: UUID
    question_number: int
    question_text: str
    question_type: str
    points: Decimal
    selected_option_id: Optional[UUID]
    answer_text: Optional[str]
    is_correct: Optional[bool]
    points_earned: Decimal
    options: List[OptionWithCorrect]

    model_config = {"from_attributes": True}


class SessionResult(BaseModel):
    id: UUID
    exam_id: UUID
    exam_title: str
    subject_name: str
    exam_type_code: str
    started_at: datetime
    submitted_at: Optional[datetime]
    time_spent_seconds: Optional[int]
    status: str
    total_score: Decimal
    total_points: int
    grade: Decimal
    passed: bool
    answers: List[AnswerResult]

    model_config = {"from_attributes": True}


# ── Admin stats ───────────────────────────────────────────────────────────────

class AdminStats(BaseModel):
    total_users: int
    active_users: int
    total_exams: int
    published_exams: int
    total_sessions: int
    sessions_today: int
    average_grade: Optional[float]
    pass_rate: Optional[float]
