from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime

db = SQLAlchemy()


# =========================
# USER MODEL
# =========================
class User(UserMixin, db.Model):
    __tablename__ = "users"

    id = db.Column(
        db.Integer,
        primary_key=True
    )

    name = db.Column(
        db.String(100),
        nullable=False
    )

    username = db.Column(
        db.String(100),
        unique=True,
        nullable=False
    )

    password = db.Column(
        db.String(255),
        nullable=False
    )

    role = db.Column(
        db.String(20),
        nullable=False,
        default="shop"
    )

    email = db.Column(
        db.String(255),
        unique=True,
        nullable=True
    )

    # =====================================
    # IMPORTANT:
    # DO NOT DELETE VIDEOS WHEN USER
    # IS DELETED.
    # =====================================

    videos = db.relationship(
        "Video",
        backref="uploader",
        lazy=True
    )

    downloads = db.relationship(
        "Download",
        backref="user",
        lazy=True,
        cascade="all, delete"
    )

    def set_password(self, raw_password):
        self.password = generate_password_hash(
            raw_password
        )

    def check_password(self, raw_password):
        return check_password_hash(
            self.password,
            raw_password
        )

    def __repr__(self):
        return f"<User {self.username}>"
        
# =========================
# VIDEO MODEL
# =========================
class Video(db.Model):
    __tablename__ = "videos"

    id = db.Column(
        db.Integer,
        primary_key=True
    )

    title = db.Column(
        db.String(255),
        nullable=False
    )

    filename = db.Column(
        db.String(255),
        nullable=False
    )

    upload_date = db.Column(
        db.DateTime,
        default=datetime.utcnow
    )

    # =====================================
    # IMPORTANT:
    # VIDEO SURVIVES USER DELETION.
    # =====================================

    uploaded_by = db.Column(
        db.Integer,
        db.ForeignKey(
            "users.id",
            ondelete="SET NULL"
        ),
        nullable=True
    )

    downloads = db.relationship(
        "Download",
        backref="video",
        lazy=True,
        cascade="all, delete"
    )

    def __repr__(self):
        return f"<Video {self.title}>"

# =========================
# DOWNLOAD MODEL
# =========================
class Download(db.Model):
    __tablename__ = "downloads"

    id = db.Column(db.Integer, primary_key=True)

    user_id = db.Column(
        db.Integer,
        db.ForeignKey("users.id"),
        nullable=False
    )

    video_id = db.Column(
        db.Integer,
        db.ForeignKey("videos.id"),
        nullable=False
    )

    download_date = db.Column(
        db.DateTime,
        default=datetime.utcnow
    )


class Activity(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    message = db.Column(db.String(255))
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
    
    
class LoginAttempt(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    username = db.Column(db.String(100))

    ip_address = db.Column(db.String(50))

    successful = db.Column(db.Boolean)

    timestamp = db.Column(db.DateTime, default=datetime.utcnow)

# =========================
# PASSWORD RESET TOKEN
# =========================
class PasswordResetToken(db.Model):
    __tablename__ = "password_reset_tokens"

    id = db.Column(
        db.Integer,
        primary_key=True
    )

    user_id = db.Column(
        db.Integer,
        db.ForeignKey("users.id"),
        nullable=False
    )

    token = db.Column(
        db.String(255),
        unique=True,
        nullable=False
    )

    expires_at = db.Column(
        db.DateTime,
        nullable=False
    )

    created_at = db.Column(
        db.DateTime,
        default=datetime.utcnow
    )

    user = db.relationship(
        "User",
        backref=db.backref(
            "password_reset_tokens",
            lazy=True,
            cascade="all, delete-orphan"
        )
    )

# =========================
# PLAYLIST MODEL
# =========================
class Playlist(db.Model):
    __tablename__ = "playlists"

    id = db.Column(
        db.Integer,
        primary_key=True
    )

    name = db.Column(
        db.String(255),
        nullable=False
    )

    # =====================================
    # IMPORTANT:
    # PLAYLIST SURVIVES CREATOR DELETION.
    # =====================================

    created_by = db.Column(
        db.Integer,
        db.ForeignKey(
            "users.id",
            ondelete="SET NULL"
        ),
        nullable=True
    )

    created_at = db.Column(
        db.DateTime,
        default=datetime.utcnow
    )

    creator = db.relationship(
        "User",
        backref=db.backref(
            "playlists",
            lazy=True
        ),
        passive_deletes=True
    )

    videos = db.relationship(
        "PlaylistVideo",
        backref="playlist",
        lazy=True,
        cascade="all, delete-orphan",
        order_by="PlaylistVideo.position"
    )

    def __repr__(self):
        return f"<Playlist {self.name}>"
        
# =========================
# PLAYLIST VIDEO MODEL
# =========================
class PlaylistVideo(db.Model):
    __tablename__ = "playlist_videos"

    id = db.Column(
        db.Integer,
        primary_key=True
    )

    playlist_id = db.Column(
        db.Integer,
        db.ForeignKey("playlists.id"),
        nullable=False
    )

    video_id = db.Column(
        db.Integer,
        db.ForeignKey("videos.id"),
        nullable=False
    )

    position = db.Column(
        db.Integer,
        nullable=False,
        default=0
    )

    # Video represented by this playlist item
    video = db.relationship(
        "Video",
        backref=db.backref(
            "playlist_items",
            lazy=True,
            cascade="all, delete"
        )
    )

    def __repr__(self):
        return (
            f"<PlaylistVideo "
            f"playlist={self.playlist_id} "
            f"video={self.video_id} "
            f"position={self.position}>"
        )
        
# =========================
# KIOSK STATUS MODEL
# =========================
class KioskStatus(db.Model):
    __tablename__ = "kiosk_status"

    id = db.Column(
        db.Integer,
        primary_key=True
    )

    user_id = db.Column(
        db.Integer,
        db.ForeignKey("users.id"),
        unique=True,
        nullable=False
    )

    status = db.Column(
        db.String(20),
        nullable=False,
        default="offline"
    )

    video_id = db.Column(
        db.Integer,
        db.ForeignKey("videos.id"),
        nullable=True
    )

    playlist_id = db.Column(
        db.Integer,
        db.ForeignKey("playlists.id"),
        nullable=True
    )

    last_seen = db.Column(
        db.DateTime,
        default=datetime.utcnow,
        nullable=False
    )

    updated_at = db.Column(
        db.DateTime,
        default=datetime.utcnow,
        onupdate=datetime.utcnow
    )

    # Shop/user associated with this kiosk
    user = db.relationship(
        "User",
        backref=db.backref(
            "kiosk_status",
            uselist=False,
            cascade="all, delete-orphan"
        )
    )

    # Current video
    video = db.relationship(
        "Video",
        foreign_keys=[video_id]
    )

    # Current playlist
    playlist = db.relationship(
        "Playlist",
        foreign_keys=[playlist_id]
    )

    def __repr__(self):
        return (
            f"<KioskStatus "
            f"user={self.user_id} "
            f"status={self.status}>"
        )

# =========================
# SEED SUPERADMIN
# =========================
def seed_superadmin():
    existing = User.query.filter_by(
        username="superadmin"
    ).first()

    if not existing:

        superadmin = User(
            name="Super Admin",
            username="superadmin",
            role="superadmin"
        )

        superadmin.set_password("admin123")

        db.session.add(superadmin)
        db.session.commit()

        print(
            "SuperAdmin created -> "
            "username: superadmin | password: admin123"
        )