from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

db = SQLAlchemy()


# Association table for article tags
article_tags = db.Table(
    'article_tags',
    db.Column('article_id', db.Integer, db.ForeignKey('articles.id'), primary_key=True),
    db.Column('tag_id', db.Integer, db.ForeignKey('tags.id'), primary_key=True),
)


class User(UserMixin, db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False, index=True)
    email = db.Column(db.String(120), unique=True, nullable=False, index=True)
    password_hash = db.Column(db.String(256), nullable=False)
    display_name = db.Column(db.String(120), nullable=False)
    display_name_ar = db.Column(db.String(120), default='')
    role = db.Column(db.String(20), nullable=False, default='editor')  # 'admin' or 'editor'
    is_active_user = db.Column(db.Boolean, default=True)
    avatar = db.Column(db.String(255), default='')
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    articles = db.relationship('Article', backref='author', lazy='dynamic')

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    @property
    def is_admin(self):
        return self.role == 'admin'


class Category(db.Model):
    __tablename__ = 'categories'

    id = db.Column(db.Integer, primary_key=True)
    name_en = db.Column(db.String(100), nullable=False, unique=True)
    name_ar = db.Column(db.String(100), nullable=False)
    slug = db.Column(db.String(120), unique=True, nullable=False, index=True)
    description_en = db.Column(db.Text, default='')
    description_ar = db.Column(db.Text, default='')
    color = db.Column(db.String(7), default='#c70000')  # hex color for category
    order = db.Column(db.Integer, default=0)
    is_active = db.Column(db.Boolean, default=True)

    articles = db.relationship('Article', backref='category', lazy='dynamic')

    def name(self, lang='en'):
        return self.name_ar if lang == 'ar' else self.name_en

    def description(self, lang='en'):
        return self.description_ar if lang == 'ar' else self.description_en


class Tag(db.Model):
    __tablename__ = 'tags'

    id = db.Column(db.Integer, primary_key=True)
    name_en = db.Column(db.String(60), nullable=False, unique=True)
    name_ar = db.Column(db.String(60), default='')
    slug = db.Column(db.String(80), unique=True, nullable=False, index=True)

    def name(self, lang='en'):
        return self.name_ar if lang == 'ar' and self.name_ar else self.name_en


class Article(db.Model):
    __tablename__ = 'articles'

    id = db.Column(db.Integer, primary_key=True)

    # English content
    title_en = db.Column(db.String(300), nullable=False)
    subtitle_en = db.Column(db.String(500), default='')
    content_en = db.Column(db.Text, nullable=False)

    # Arabic content
    title_ar = db.Column(db.String(300), default='')
    subtitle_ar = db.Column(db.String(500), default='')
    content_ar = db.Column(db.Text, default='')

    slug = db.Column(db.String(350), unique=True, nullable=False, index=True)

    # Status: draft, pending, published, rejected
    status = db.Column(db.String(20), default='draft', index=True)

    # Media
    featured_image = db.Column(db.String(500), default='')
    featured_image_caption = db.Column(db.String(300), default='')
    video_url = db.Column(db.String(500), default='')       # uploaded video path
    youtube_url = db.Column(db.String(500), default='')      # YouTube embed URL
    audio_url = db.Column(db.String(500), default='')        # uploaded audio path

    # Metadata
    is_featured = db.Column(db.Boolean, default=False)
    is_breaking = db.Column(db.Boolean, default=False)
    views = db.Column(db.Integer, default=0)

    # Timestamps
    created_at = db.Column(db.DateTime, default=datetime.utcnow, index=True)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    published_at = db.Column(db.DateTime, nullable=True, index=True)

    # Foreign keys
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    category_id = db.Column(db.Integer, db.ForeignKey('categories.id'), nullable=False)

    # Tags relationship
    tags = db.relationship('Tag', secondary=article_tags, lazy='subquery',
                           backref=db.backref('articles', lazy='dynamic'))

    def title(self, lang='en'):
        return self.title_ar if lang == 'ar' and self.title_ar else self.title_en

    def subtitle(self, lang='en'):
        return self.subtitle_ar if lang == 'ar' and self.subtitle_ar else self.subtitle_en

    def content(self, lang='en'):
        return self.content_ar if lang == 'ar' and self.content_ar else self.content_en

    @property
    def is_published(self):
        return self.status == 'published'

    @property
    def reading_time(self):
        word_count = len(self.content_en.split()) if self.content_en else 0
        return max(1, word_count // 200)

    @property
    def has_media(self):
        return bool(self.video_url or self.youtube_url or self.audio_url)

    @property
    def youtube_embed_id(self):
        if not self.youtube_url:
            return None
        url = self.youtube_url
        if 'youtu.be/' in url:
            return url.split('youtu.be/')[-1].split('?')[0]
        if 'watch?v=' in url:
            return url.split('watch?v=')[-1].split('&')[0]
        if 'embed/' in url:
            return url.split('embed/')[-1].split('?')[0]
        return None


class SiteSettings(db.Model):
    __tablename__ = 'site_settings'

    id = db.Column(db.Integer, primary_key=True)
    key = db.Column(db.String(100), unique=True, nullable=False)
    value = db.Column(db.Text, default='')

    @staticmethod
    def get(key, default=''):
        setting = SiteSettings.query.filter_by(key=key).first()
        return setting.value if setting else default

    @staticmethod
    def set(key, value):
        setting = SiteSettings.query.filter_by(key=key).first()
        if setting:
            setting.value = value
        else:
            setting = SiteSettings(key=key, value=value)
            db.session.add(setting)
        db.session.commit()
