"""Pydantic schemas for all API request/response models."""
from datetime import datetime
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field


# ── Config for all schemas ──────────────────────────────
class ORMBase(BaseModel):
    model_config = ConfigDict(from_attributes=True)


# ── Auth ────────────────────────────────────────────────
class LoginResponse(BaseModel):
    redirect_url: str


class AuthCallbackResponse(BaseModel):
    access_token: str
    token_type: str = "bearer"
    user: "UserOut"


class UserOut(ORMBase):
    id: UUID
    email: str
    full_name: str
    display_name: str | None = None
    is_active: bool
    roles: list[str] = []


# ── Teams / Cohorts / Programs ──────────────────────────
class TeamOut(ORMBase):
    id: UUID
    name: str
    description: str | None = None


class ProgramOut(ORMBase):
    id: UUID
    name: str
    description: str | None = None
    is_active: bool


class CohortCreate(BaseModel):
    name: str
    program_id: UUID
    batch_size: int = 5
    is_active: bool = True


class CohortOut(ORMBase):
    id: UUID
    name: str
    program_id: UUID
    batch_size: int
    is_active: bool


class CohortMemberAdd(BaseModel):
    user_id: UUID
    cohort_id: UUID


# ── Modules / Rules ─────────────────────────────────────
class ModuleRuleUpdate(BaseModel):
    pass_threshold: float = Field(ge=0, le=100, default=70.0)
    is_mandatory: bool = True
    max_replays: int | None = None


class ModuleRuleOut(ORMBase):
    id: UUID
    module_id: UUID
    pass_threshold: float
    is_mandatory: bool
    max_replays: int | None = None


class ModuleCreate(BaseModel):
    program_id: UUID
    name: str
    description: str | None = None
    order_index: int = 0
    is_active: bool = True


class ModuleOut(ORMBase):
    id: UUID
    program_id: UUID
    name: str
    description: str | None = None
    order_index: int
    is_active: bool
    rules: ModuleRuleOut | None = None


# ── Questions / Options ────────────────────────────────
class QuestionOptionOut(ORMBase):
    id: UUID
    option_text: str
    is_correct: bool
    order_index: int


class QuestionOptionCreate(BaseModel):
    option_text: str
    is_correct: bool
    order_index: int = 0


class QuestionCreate(BaseModel):
    question_text: str
    topic_tag: str = "general"
    explanation: str | None = None
    confidence_score: float = 0.0
    is_ai_generated: bool = False


class QuestionOut(ORMBase):
    id: UUID
    quiz_id: UUID
    question_text: str
    topic_tag: str
    explanation: str | None = None
    confidence_score: float
    is_ai_generated: bool
    options: list[QuestionOptionOut] = []


class QuestionUpdate(BaseModel):
    question_text: str | None = None
    topic_tag: str | None = None
    explanation: str | None = None
    confidence_score: float | None = None
    options: list[QuestionOptionCreate] | None = None


# ── Quiz ────────────────────────────────────────────────
class QuizCreate(BaseModel):
    module_id: UUID
    title: str
    description: str | None = None
    requires_credit_head: bool = False


class QuizOut(ORMBase):
    id: UUID
    module_id: UUID
    title: str
    description: str | None = None
    status: str
    requires_credit_head: bool
    created_by: UUID
    questions: list[QuestionOut] = []


class QuizUpdate(BaseModel):
    title: str | None = None
    description: str | None = None
    requires_credit_head: bool | None = None


class QuizVersionOut(ORMBase):
    id: UUID
    quiz_id: UUID
    version_number: int
    published_by: UUID
    created_at: datetime


# ── Documents ───────────────────────────────────────────
class DocumentJobOut(ORMBase):
    id: UUID
    document_id: UUID
    status: str
    error_message: str | None = None
    generated_quiz_id: UUID | None = None
    created_at: datetime


class SourceDocumentOut(ORMBase):
    id: UUID
    filename: str
    file_type: str
    file_size: int
    uploaded_by: UUID
    created_at: datetime
    extracted_text: str | None = None


# ── Assignments / Attempts ─────────────────────────────
class AssignmentCreate(BaseModel):
    quiz_id: UUID
    cohort_id: UUID | None = None
    user_id: UUID | None = None
    due_date: datetime | None = None


class AssignmentOut(ORMBase):
    id: UUID
    quiz_id: UUID
    cohort_id: UUID | None = None
    user_id: UUID | None = None
    due_date: datetime | None = None
    is_active: bool
    best_score: float | None = None
    is_passed: bool | None = None
    attempt_count: int | None = None
    quiz_title: str | None = None


class AttemptCreate(BaseModel):
    assignment_id: UUID
    module_id: UUID


class AttemptAnswerCreate(BaseModel):
    question_id: UUID
    selected_option_id: UUID


class AttemptAnswerOut(ORMBase):
    id: UUID
    question_id: UUID
    selected_option_id: UUID | None = None
    is_correct: bool


class AttemptOut(ORMBase):
    id: UUID
    assignment_id: UUID
    learner_id: UUID
    module_id: UUID
    status: str
    score: float
    correct_count: int
    total_questions: int
    started_at: datetime
    completed_at: datetime | None = None


class AnswerResult(BaseModel):
    """Returned after each answer so the learner sees immediate feedback."""
    question_id: UUID
    selected_option_id: UUID
    is_correct: bool
    explanation: str | None = None
    correct_option_id: UUID | None = None


class AttemptComplete(BaseModel):
    """Final result after completing the quiz."""
    attempt_id: UUID
    score: float
    correct_count: int
    total_questions: int
    passed: bool
    best_score: float
    weak_topics: list[str] = []


# ── Reports ─────────────────────────────────────────────
class WeakTopicRow(BaseModel):
    learner_id: UUID
    learner_name: str
    module_id: UUID
    module_name: str
    topic_tag: str
    total_questions: int
    correct_questions: int
    weakness_ratio: float


class LeaderboardRow(BaseModel):
    rank: int
    user_id: UUID
    user_name: str
    score: float
    streak_count: int
    mastery_points: float
    improvement_points: float
    consistency_points: float


class ReadinessRow(BaseModel):
    learner_id: UUID
    learner_name: str
    module_id: UUID
    module_name: str
    best_score: float
    signed_off: bool
    signoff_status: str | None = None


class CompletionRow(BaseModel):
    learner_id: UUID
    learner_name: str
    module_id: UUID
    module_name: str
    best_score: float
    latest_score: float
    attempt_count: int
    is_passed: bool
    signed_off: bool


# ── Sign-off / Certificates ────────────────────────────
class SignoffCreate(BaseModel):
    learner_id: UUID
    module_id: UUID
    status: str  # approved / rejected
    comments: str | None = None


class SignoffOut(ORMBase):
    id: UUID
    learner_id: UUID
    module_id: UUID
    manager_id: UUID
    status: str
    comments: str | None = None
    created_at: datetime


class CertificateOut(ORMBase):
    id: UUID
    learner_id: UUID
    module_id: UUID
    certificate_number: str
    issued_at: datetime


# ── Audit ──────────────────────────────────────────────
class AuditLogOut(ORMBase):
    id: UUID
    actor_id: UUID | None = None
    action: str
    entity_type: str
    entity_id: UUID | None = None
    details: dict = {}
    ip_address: str | None = None
    created_at: datetime


# ── Health ─────────────────────────────────────────────
class HealthResponse(BaseModel):
    status: str = "ok"
    database: str = "unknown"
    redis: str = "unknown"


# Resolve forward ref
AuthCallbackResponse.model_rebuild()
