from typing import List, Optional
from datetime import datetime
from sqlmodel import Field, Relationship, SQLModel, Column, JSON
from sqlalchemy import UniqueConstraint

# User Model
class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    username: str = Field(index=True, unique=True)
    password_hash: str
    is_active: bool = Field(default=True)
    created_at: datetime = Field(default_factory=datetime.utcnow)
    google_id: Optional[str] = Field(default=None, index=True, unique=True)
    email: Optional[str] = Field(default=None, unique=True, index=True)
    display_name: Optional[str] = Field(default=None)
    # Profile fields
    age: Optional[int] = Field(default=None)
    career: Optional[str] = Field(default=None)
    education: Optional[str] = Field(default=None)
    linkedin_url: Optional[str] = Field(default=None)
    community_role: Optional[str] = Field(default=None)  # "mentor" | "mentee" | None
    bio: Optional[str] = Field(default=None)
    tech_skills: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    lockout_until: Optional[datetime] = Field(default=None)
    reset_token: Optional[str] = Field(default=None, unique=True, index=True)
    reset_token_expires: Optional[datetime] = Field(default=None)


class MentorSlot(SQLModel, table=True):
    __tablename__ = "mentor_slot"

    id: Optional[int] = Field(default=None, primary_key=True)
    mentor_id: int = Field(foreign_key="user.id", index=True)
    start_time: datetime
    end_time: datetime
    title: Optional[str] = Field(default=None)
    notes: Optional[str] = Field(default=None)
    is_booked: bool = Field(default=False)
    booked_by_id: Optional[int] = Field(default=None, foreign_key="user.id")
    created_at: datetime = Field(default_factory=datetime.utcnow)

# Topic Model
class Topic(SQLModel, table=True):
    id: str = Field(primary_key=True)  # Using string ID like 'javascript' from source
    name: str
    icon: str
    
    quizzes: List["Quiz"] = Relationship(back_populates="topic")

# Quiz Model
class Quiz(SQLModel, table=True):
    id: str = Field(primary_key=True)
    name: str
    topic_id: str = Field(foreign_key="topic.id")
    
    topic: Optional[Topic] = Relationship(back_populates="quizzes")
    questions: List["Question"] = Relationship(back_populates="quiz")

# Question Model
class Question(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    content: str
    options: List[str] = Field(sa_column=Column(JSON))
    answer: int
    difficulty: str
    sub_topic: str
    is_shufflable: bool = Field(default=True)
    quiz_id: str = Field(foreign_key="quiz.id")
    
    quiz: Optional[Quiz] = Relationship(back_populates="questions")

# Activity Log
class UserActivity(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: Optional[int] = Field(foreign_key="user.id", nullable=True)
    action: str
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    details: Optional[str] = None


# User session / token tracking for revocation
class UserSession(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: Optional[int] = Field(foreign_key="user.id", index=True)
    jti: str = Field(index=True, unique=True)
    issued_at: datetime = Field(default_factory=datetime.utcnow)
    expires_at: datetime
    revoked: bool = Field(default=False)


# Refresh token (opaque token stored hashed for rotation + revocation)
class RefreshToken(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: int = Field(foreign_key="user.id", index=True)
    token_hash: str = Field(index=True, unique=True)
    session_jti: Optional[str] = Field(default=None, index=True)
    issued_at: datetime = Field(default_factory=datetime.utcnow)
    expires_at: datetime
    revoked: bool = Field(default=False)
    replaced_by: Optional[int] = Field(default=None, foreign_key="refreshtoken.id")

# Quiz History
class QuizHistory(SQLModel, table=True):
    __table_args__ = (UniqueConstraint("user_id", "quiz_id"),)

    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: int = Field(foreign_key="user.id", index=True)
    quiz_id: str = Field(foreign_key="quiz.id", index=True)
    passed_questions: List[int] = Field(default=[], sa_column=Column(JSON))
    failed_questions: List[int] = Field(default=[], sa_column=Column(JSON))
    score: int = Field(default=0)
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    # Relationships are optional but helpful
    user: Optional[User] = Relationship()
    quiz: Optional[Quiz] = Relationship()

# Study Plan Item — tracks questions the user needs to review
class StudyPlanItem(SQLModel, table=True):
    __table_args__ = (UniqueConstraint("user_id", "question_id"),)

    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: int = Field(foreign_key="user.id", index=True)
    question_id: int = Field(foreign_key="question.id")
    topic_id: str = Field(foreign_key="topic.id", index=True)
    sub_topic: str = Field(default="")
    status: str = Field(default="not_started")  # "not_started", "in_progress", "done"
    source: str = Field(default="manual")  # "auto" or "manual"
    created_at: datetime = Field(default_factory=datetime.utcnow)

    question: Optional[Question] = Relationship()

# Question Vote — one vote per user per question
class QuestionVote(SQLModel, table=True):
    __table_args__ = (UniqueConstraint("user_id", "question_id"),)

    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: int = Field(foreign_key="user.id", index=True)
    question_id: int = Field(foreign_key="question.id", index=True)
    value: int  # +1 or -1
    created_at: datetime = Field(default_factory=datetime.utcnow)

