from sqlalchemy import (
    Column, Integer, String, Boolean, DateTime, Enum, Text, JSON,
    ForeignKey, UniqueConstraint, func
)
from sqlalchemy.orm import relationship
from app.core.database import Base


class Subject(Base):
    __tablename__ = "subjects"

    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)
    slug = Column(String(100), unique=True, nullable=False)
    description = Column(Text, nullable=True)
    icon_url = Column(String(500), nullable=True)
    color_hex = Column(String(7), default="#4F46E5")
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())

    subject_grades = relationship("SubjectGrade", back_populates="subject")
    academic_summaries = relationship("AcademicProgressSummary", back_populates="subject")


class Grade(Base):
    __tablename__ = "grades"

    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)
    slug = Column(String(50), unique=True, nullable=False)
    description = Column(String(255), nullable=True)
    level_order = Column(Integer, nullable=False)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())

    subject_grades = relationship("SubjectGrade", back_populates="grade")
    enrollments = relationship("SchoolStudentEnrollment", back_populates="grade")
    academic_summaries = relationship("AcademicProgressSummary", back_populates="grade")


class SubjectGrade(Base):
    __tablename__ = "subject_grades"

    id = Column(Integer, primary_key=True)
    subject_id = Column(Integer, ForeignKey("subjects.id", ondelete="CASCADE"), nullable=False)
    grade_id = Column(Integer, ForeignKey("grades.id", ondelete="CASCADE"), nullable=False)
    curriculum_notes = Column(Text, nullable=True)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())

    __table_args__ = (UniqueConstraint("subject_id", "grade_id", name="uk_subject_grade"),)

    subject = relationship("Subject", back_populates="subject_grades")
    grade = relationship("Grade", back_populates="subject_grades")
    topics = relationship("Topic", back_populates="subject_grade")
    games = relationship("Game", back_populates="subject_grade")


class Package(Base):
    __tablename__ = "packages"

    id = Column(Integer, primary_key=True)
    name = Column(Enum("freemium", "premium"), nullable=False)
    slug = Column(String(50), unique=True, nullable=False)
    display_name = Column(String(100), nullable=False)
    description = Column(Text, nullable=True)
    price = Column(Integer, default=0)
    currency = Column(String(3), default="UGX")
    duration_days = Column(Integer, nullable=True)
    is_offline_capable = Column(Boolean, default=False)
    requires_subscription_check = Column(Boolean, default=False)
    grace_period_days = Column(Integer, default=3)
    features = Column(JSON, nullable=True)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())

    topics = relationship("Topic", back_populates="package")
    subscriptions = relationship("Subscription", back_populates="package")


class Topic(Base):
    __tablename__ = "topics"

    id = Column(Integer, primary_key=True)
    subject_grade_id = Column(Integer, ForeignKey("subject_grades.id", ondelete="CASCADE"), nullable=False)
    package_id = Column(Integer, ForeignKey("packages.id"), nullable=False)
    name = Column(String(255), nullable=False)
    slug = Column(String(255), nullable=False)
    description = Column(Text, nullable=True)
    thumbnail_url = Column(String(500), nullable=True)
    sequence_order = Column(Integer, default=1)
    is_offline_available = Column(Boolean, default=False)
    offline_content_version = Column(String(20), default="1.0.0")
    offline_content_hash = Column(String(64), nullable=True)
    total_levels = Column(Integer, default=5)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())

    subject_grade = relationship("SubjectGrade", back_populates="topics")
    package = relationship("Package", back_populates="topics")
    levels = relationship("TopicLevel", back_populates="topic", cascade="all, delete-orphan")
    offline_downloads = relationship("OfflineDownload", back_populates="topic")


class TopicLevel(Base):
    __tablename__ = "topic_levels"

    id = Column(Integer, primary_key=True)
    topic_id = Column(Integer, ForeignKey("topics.id", ondelete="CASCADE"), nullable=False)
    level_number = Column(Integer, nullable=False)
    name = Column(String(255), nullable=True)
    description = Column(Text, nullable=True)
    instructions = Column(Text, nullable=True)
    thumbnail_url = Column(String(500), nullable=True)
    passing_score = Column(Integer, default=70)
    time_limit_seconds = Column(Integer, default=300)
    xp_reward = Column(Integer, default=10)
    stars_max = Column(Integer, default=3)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())

    __table_args__ = (UniqueConstraint("topic_id", "level_number", name="uk_topic_level"),)

    topic = relationship("Topic", back_populates="levels")
    questions = relationship("Question", back_populates="level", cascade="all, delete-orphan")
    game_levels = relationship("GameLevel", back_populates="topic_level")
    player_progress = relationship("PlayerProgress", back_populates="topic_level")


class Question(Base):
    __tablename__ = "questions"

    id = Column(Integer, primary_key=True)
    level_id = Column(Integer, ForeignKey("topic_levels.id", ondelete="CASCADE"), nullable=False)
    question_text = Column(Text, nullable=False)
    question_type = Column(
        Enum("multiple_choice", "true_false", "drag_drop", "fill_blank", "matching", "calculation"),
        default="multiple_choice"
    )
    difficulty = Column(Enum("easy", "medium", "hard"), default="medium")
    sequence_order = Column(Integer, default=1)
    time_limit_seconds = Column(Integer, default=60)
    points = Column(Integer, default=10)
    hint_text = Column(Text, nullable=True)
    explanation = Column(Text, nullable=True)
    media_url = Column(Text, nullable=True)
    tag = Column(String(50), nullable=True)
    submitted_by_teacher_id = Column(Integer, nullable=True)
    is_verified = Column(Boolean, default=False)
    verified_by_user_id = Column(Integer, nullable=True)
    verified_at = Column(DateTime, nullable=True)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())

    level = relationship("TopicLevel", back_populates="questions")
    answers = relationship("AnswerOption", back_populates="question", cascade="all, delete-orphan")
    responses = relationship("PlayerResponse", back_populates="question")


class AnswerOption(Base):
    __tablename__ = "answer_options"

    id = Column(Integer, primary_key=True)
    question_id = Column(Integer, ForeignKey("questions.id", ondelete="CASCADE"), nullable=False)
    answer_text = Column(Text, nullable=False)
    is_correct = Column(Boolean, default=False)
    display_order = Column(Integer, default=1)
    explanation = Column(Text, nullable=True)
    asset_2d_id = Column(Integer, ForeignKey("game_assets.id"), nullable=True)
    asset_3d_id = Column(Integer, ForeignKey("game_assets.id"), nullable=True)
    asset_vr_id = Column(Integer, ForeignKey("game_assets.id"), nullable=True)
    asset_group = Column(Enum("target", "action"), nullable=True)
    monetary_value = Column(Integer, nullable=True)
    quantity = Column(Integer, default=1)
    created_at = Column(DateTime, server_default=func.now())

    question = relationship("Question", back_populates="answers")
    asset_2d = relationship("GameAsset", foreign_keys=[asset_2d_id])
    asset_3d = relationship("GameAsset", foreign_keys=[asset_3d_id])
    asset_vr = relationship("GameAsset", foreign_keys=[asset_vr_id])


class TeacherQuestionSubmission(Base):
    __tablename__ = "teacher_question_submissions"

    id = Column(Integer, primary_key=True)
    teacher_user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
    topic_level_id = Column(Integer, ForeignKey("topic_levels.id"), nullable=False)
    question_text = Column(Text, nullable=False)
    question_type = Column(
        Enum("multiple_choice", "true_false", "drag_drop", "fill_blank", "matching"),
        nullable=False
    )
    difficulty = Column(Enum("easy", "medium", "hard"), default="medium")
    answers_json = Column(JSON, nullable=True)
    hint_text = Column(Text, nullable=True)
    explanation = Column(Text, nullable=True)
    status = Column(
        Enum("pending", "approved", "rejected", "revision_needed"), default="pending"
    )
    reviewed_by_user_id = Column(Integer, nullable=True)
    reviewed_at = Column(DateTime, nullable=True)
    review_comments = Column(Text, nullable=True)
    approved_question_id = Column(Integer, ForeignKey("questions.id"), nullable=True)
    created_at = Column(DateTime, server_default=func.now())
    updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())

    teacher_user = relationship("TeacherProfile", primaryjoin="foreign(TeacherQuestionSubmission.teacher_user_id) == TeacherProfile.user_id", viewonly=True)
    topic_level = relationship("TopicLevel")
    approved_question = relationship("Question", foreign_keys=[approved_question_id])
