from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import declarative_base
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
from flask_login import UserMixin

import uuid
import hashlib

Base = declarative_base()
db = SQLAlchemy(model_class=Base)

class User(Base, UserMixin):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    first_name = db.Column(db.String(255), nullable=False)
    last_name = db.Column(db.String(255), nullable=False)
    email = db.Column(db.String(255), unique=True, nullable=False)
    password_hash = db.Column(db.String(2048), nullable=False)
    imap_config = db.Column(db.JSON) # Using db.JSON instead of db.JSONB for compatibility
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    def set_password(self, password):
        """Hash and set the password."""
        self.password_hash = generate_password_hash(password)
    
    def check_password(self, password):
        """Check if the provided password matches the stored hash."""
        return check_password_hash(self.password_hash, password)
    
    def __repr__(self):
        return f'<User {self.first_name} {self.last_name} ({self.email})>'

class Folder(Base):
    __tablename__ = 'folders'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    name = db.Column(db.String(255), nullable=False)
    rule_text = db.Column(db.Text)
    priority = db.Column(db.Integer)
    organize_enabled = db.Column(db.Boolean, default=True)
    folder_type = db.Column(db.String(20), default='destination', nullable=False)
    total_count = db.Column(db.Integer, default=0)
    pending_count = db.Column(db.Integer, default=0)
    emails_count = db.Column(db.Integer, default=0)
    recent_emails = db.Column(db.JSON, default=list)  # Store recent email subjects with dates
    
    user = db.relationship('User', backref=db.backref('folders', lazy=True))

class ProcessedEmail(Base):
    __tablename__ = 'processed_emails'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    folder_id = db.Column(db.Integer, db.ForeignKey('folders.id'), nullable=False)
    email_uid = db.Column(db.String(255), nullable=False)
    folder_name = db.Column(db.String(255), nullable=False)
    is_processed = db.Column(db.Boolean, default=False)
    first_seen_at = db.Column(db.DateTime, default=datetime.utcnow)
    processed_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    user = db.relationship('User', backref=db.backref('processed_emails', lazy=True))
    folder = db.relationship('Folder', backref=db.backref('processed_emails', lazy=True))
    
    def __repr__(self):
        return f'<ProcessedEmail {self.email_uid} for folder {self.folder_name}>'

class AIRuleCache(Base):
    """Cache for AI-generated rules to improve performance and reduce API calls."""
    __tablename__ = 'ai_rule_cache'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    folder_name = db.Column(db.String(255), nullable=False)
    folder_type = db.Column(db.String(20), nullable=False)
    rule_text = db.Column(db.Text, nullable=False)
    rule_metadata = db.Column(db.JSON)  # Quality score, model info, etc.
    cache_key = db.Column(db.String(64), unique=True, nullable=False)  # MD5 hash of inputs
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    expires_at = db.Column(db.DateTime, nullable=False)
    is_active = db.Column(db.Boolean, default=True)
    
    user = db.relationship('User', backref=db.backref('ai_rule_cache', lazy=True))
    
    def __repr__(self):
        return f'<AIRuleCache {self.folder_name} for user {self.user_id}>'
    
    @staticmethod
    def generate_cache_key(folder_name: str, folder_type: str, rule_type: str = 'single', rule_text: str = '') -> str:
        """Generate a unique cache key based on inputs."""
        input_string = f"{folder_name}:{folder_type}:{rule_type}:{rule_text}"
        return hashlib.md5(input_string.encode()).hexdigest()
    
    def is_expired(self) -> bool:
        """Check if cache entry is expired."""
        return datetime.utcnow() > self.expires_at