from sqlalchemy import Column, Integer,Boolean, DateTime, String, ForeignKey, TIMESTAMP, Text, text, Enum, JSON, UniqueConstraint, func
from passlib.context import CryptContext
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import enum
from .database import Base

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

class Courses(Base):
    __tablename__ = "courses"
    
    id = Column(Integer, primary_key=True, index=True)
    course_id = Column(String(255), nullable=True)
    user_id = Column(String(255), nullable=True)
    canvas_course_id = Column(Integer, nullable=True)
    topic = Column(String, nullable=True)
    task_id = Column(String(255), nullable=True)
    skills = Column(String(255), nullable=True)
    degree = Column(String(255), nullable=True)
    allocated_time = Column(String(255), nullable=True)
    mode_of_delivery = Column(String(255), nullable=True)
    tone = Column(String(255), nullable=True)
    weblinks = Column(Text, nullable=True)
    language = Column(String(255), nullable=True)
    content_description = Column(Text, nullable=True)
    content_outcomes = Column(Text, nullable=True)
    taxonomy = Column(Text, nullable=True)
    content_objectives = Column(Text, nullable=True)
    content_summary = Column(Text, nullable=True)
    outline = Column(Text, nullable=True)
    learning_approach = Column(Text, nullable=True)
    no_of_modules = Column(Integer, nullable=True)
    level_of_difficulty = Column(String(255), nullable=True)
    type_of_assessment = Column(String(255), nullable=True)
    no_of_questions = Column(Integer, nullable=True)
    markdown_content = Column(Text, nullable=True)
    markdown_url = Column(String, nullable=True)
    email = Column(String(255), unique=True, nullable=True)
    status = Column(String(255), nullable=True)
    course_step = Column(Integer, default=1, nullable=False)
    course_imscc_url = Column(String, nullable=True)
    is_deleted = Column(String(10), default="no", nullable=False)
    created_at = Column(TIMESTAMP, default=datetime.utcnow)
    updated_at = Column(TIMESTAMP, default=datetime.utcnow, onupdate=datetime.utcnow)
    deleted_at = Column(TIMESTAMP, nullable=True)
    
    modules = relationship("CourseModules", back_populates="course", cascade="all, delete-orphan")


class CourseModules(Base):
    __tablename__ = "course_modules"
    
    id = Column(Integer, primary_key=True, index=True)
    course_id = Column(Integer, ForeignKey("courses.id"), nullable=False)
    module_title = Column(String(255), nullable=False)
    module_subtopic = Column(Text, nullable=True)
    estimated_time = Column(String(255), nullable=True)
    assessment = Column(String(255), nullable=True)
    recommended_resourses = Column(Text, nullable=True)
    skills = Column(Text, nullable=True)
    
    course = relationship("Courses", back_populates="modules")

class LoginState(Base):
    __tablename__ = "login_states"

    id = Column(Integer, primary_key=True, index=True)
    state = Column(String(255), nullable=False, unique=True)
    tenant_domain = Column(String(255), nullable=False)
    created_at = Column(TIMESTAMP, default=datetime.utcnow)

class LMSPlatform(Base):
    __tablename__ = "lms_platforms"

    id = Column(Integer, primary_key=True, index=True)
    issuer = Column(String(255), nullable=False)       # e.g., https://canvas.instructure.com
    tenant_domain = Column(String(255), nullable=True)
    tenant_id = Column(String(255), nullable=True)
    tenant_name = Column(String(255), nullable=True)
    client_id = Column(String(255), nullable=False)    # Tool client_id
    client_secret = Column(String(255), nullable=True) # Tool client_secret
    rest_client_id = Column(String(255), nullable=True)  # Optional REST API client_id
    rest_client_secret = Column(String(255), nullable=True)  # Optional REST API client
    jwks_url = Column(String(500), nullable=False)
    token_url = Column(String(500), nullable=False)
    accounts = Column(Text, nullable=True)          # JSON list of accounts

    __table_args__ = (
        UniqueConstraint("issuer", "client_id", name="unique_platform"),
    )

    deployments = relationship("Deployment", back_populates="platform")
    users = relationship("User", back_populates="platform")
    # lms_users = relationship("LMSUser", back_populates="platform")
    tokens = relationship("AccessToken", back_populates="platform")


class Deployment(Base):
    __tablename__ = "deployments"

    id = Column(Integer, primary_key=True, index=True)
    platform_id = Column(Integer, ForeignKey("lms_platforms.id"), nullable=False)
    deployment_id = Column(String(255), nullable=False)
    context_id = Column(String(255))                   # course context
    name = Column(String(255))                         # optional label
    created_at = Column(TIMESTAMP, default=datetime.utcnow)

    __table_args__ = (
        UniqueConstraint("platform_id", "deployment_id", name="unique_deployment"),
    )

    platform = relationship("LMSPlatform", back_populates="deployments")
    tokens = relationship("AccessToken", back_populates="deployment")


# class LMSUser(Base):
#     __tablename__ = "lms_users"

#     id = Column(Integer, primary_key=True, index=True)
#     platform_id = Column(Integer, ForeignKey("lms_platforms.id"), nullable=False)
#     sub = Column(String(255), nullable=False)          # LTI subject claim
#     email = Column(String(255))
#     name = Column(String(255))
#     given_name = Column(String(255))
#     family_name = Column(String(255))
#     roles = Column(Text)                               # JSON or CSV of roles
#     last_launch = Column(TIMESTAMP, default=datetime.utcnow)

#     __table_args__ = (
#         UniqueConstraint("platform_id", "sub", name="unique_user"),
#     )
#     platform = relationship("LMSPlatform", back_populates="lms_users")
#     tokens = relationship("AccessToken", back_populates="user")


class AccessToken(Base):
    __tablename__ = "access_tokens"

    id = Column(Integer, primary_key=True, index=True)
    platform_id = Column(Integer, ForeignKey("lms_platforms.id"), nullable=False)
    deployment_id = Column(Integer, ForeignKey("deployments.id"), nullable=False)
    user_id = Column(Integer, ForeignKey("users.id"))
    scope = Column(Text)                               # JSON list of scopes
    token = Column(Text, nullable=False)               # actual access token
    rest_api_token = Column(Text, nullable=True)        # optional token for REST API calls
    refresh_token = Column(Text, nullable=True)
    expires_at = Column(TIMESTAMP, nullable=False)
    created_at = Column(TIMESTAMP, default=datetime.utcnow)

    platform = relationship("LMSPlatform", back_populates="tokens")
    deployment = relationship("Deployment", back_populates="tokens")
    user = relationship("User", back_populates="tokens")

class SectionStatus(str, enum.Enum):
    active = "active"
    inactive = "inactive"
    deleted = "deleted"


class Section(Base):
    __tablename__ = "sections"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    name = Column(String(255), nullable=True)
    key = Column(String(255), nullable=True)
    status = Column(
        Enum(SectionStatus),
        nullable=False,
        server_default="active"
    )
    created_at = Column(
        TIMESTAMP,
        nullable=False,
        server_default=text("CURRENT_TIMESTAMP")
    )
    updated_at = Column(
        TIMESTAMP,
        nullable=False,
        server_default=text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
    )

    permissions = relationship("Permission", back_populates="section", cascade="all, delete-orphan")

class Permission(Base):
    __tablename__ = "permissions"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    role_id = Column(Integer, ForeignKey("roles.id"), nullable=False)
    section_id = Column(Integer, ForeignKey("sections.id"), nullable=False)

    create = Column(Boolean, server_default="0", nullable=False)
    view = Column(Boolean, server_default="1", nullable=False)
    edit = Column(Boolean, server_default="0", nullable=False)
    delete = Column(Boolean, server_default="0", nullable=False)

    created_at = Column(
        TIMESTAMP,
        nullable=False,
        server_default=text("CURRENT_TIMESTAMP")
    )
    updated_at = Column(
        TIMESTAMP,
        nullable=False,
        server_default=text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
    )

    # relationships (optional, only if you want to join with roles/sections)
    role = relationship("Role", back_populates="permissions")
    section = relationship("Section", back_populates="permissions")


class Role(Base):
    __tablename__ = "roles"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, unique=True, nullable=False)

    users = relationship("User", back_populates="role")
    permissions = relationship("Permission", back_populates="role")

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, nullable=False)
    first_name = Column(String, nullable=True)
    last_name = Column(String, nullable=True)
    email = Column(String, unique=True, index=True, nullable=False)
    password_hash = Column(String, nullable=False)
    is_active = Column(Boolean, default=True)
    role_id = Column(Integer, ForeignKey("roles.id"), nullable=False)
    platform_id = Column(Integer, ForeignKey("lms_platforms.id"), nullable=False)
    sub = Column(String(255), nullable=True)          # LTI subject claim
    lti_roles = Column(Text, nullable=True)            # JSON or CSV of LTI roles
    activation_date = Column(DateTime, nullable=True)
    last_login = Column(DateTime, nullable=True)
    is_email_verified = Column(Boolean, default=False)
    is_phone_verified = Column(Boolean, default=False)
    phone_number = Column(String, nullable=True)
    profile_picture = Column(String, nullable=True)
    department = Column(String, nullable=True)
    educational_degree = Column(String, nullable=True)
    subscription_package = Column(String, nullable=True)
    subscription_start_date = Column(DateTime, nullable=True)
    subscription_end_date = Column(DateTime, nullable=True)
    subscription_status = Column(String, nullable=True)  # e.g., 'active', 'expired', 'cancelled'
    subscription_renewal_date = Column(DateTime, nullable=True)
    last_launch = Column(TIMESTAMP, default=datetime.utcnow)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    __table_args__ = (
        UniqueConstraint("platform_id", "sub", name="unique_user"),
    )
    tokens = relationship("AccessToken", back_populates="user")
    # Add relationship to LMSPlatform
    platform = relationship("LMSPlatform", back_populates="users")
    role = relationship("Role", back_populates="users")  # Assuming a Role model exists
    course_logs = relationship("UserCourseLog", back_populates="user", cascade="all, delete")

class UserCourseLog(Base):
    __tablename__ = "user_course_logs"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE", onupdate="CASCADE"), nullable=False, index=True)
    platform_id = Column(Integer, ForeignKey("lms_platforms.id"), nullable=False)
    number_of_course = Column(Integer, nullable=False)
    type = Column(String(100), nullable=False)

    created_at = Column(TIMESTAMP, server_default=func.now(), nullable=False)
    updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now(), nullable=False)

    # Relationship with users table
    user = relationship("User", back_populates="course_logs")

class LMSCourseLog(Base):
    __tablename__ = "lms_course_log"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    course_id = Column(Integer, nullable=False)
    lms_course_id = Column(Integer, nullable=False)
    course_info = Column(Text, nullable=False)
    migration_info = Column(Text, nullable=False)
    
    created_at = Column(TIMESTAMP, server_default=func.now(), nullable=False)
    updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now(), nullable=False)