from datetime import datetime
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from app.extensions import db, login_manager


class User(UserMixin, db.Model):
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True, nullable=False, index=True)
    password_hash = db.Column(db.String(255), nullable=True)  # Nullable for Google-only users
    name = db.Column(db.String(255), nullable=False)
    language_pref = db.Column(db.String(5), default="ar")
    is_admin = db.Column(db.Boolean, default=False)
    email_verified = db.Column(db.Boolean, default=False)
    email_verified_at = db.Column(db.DateTime, nullable=True)
    avatar_url = db.Column(db.String(500), nullable=True)
    totp_secret = db.Column(db.String(64), nullable=True)
    two_factor_enabled = db.Column(db.Boolean, default=False)
    currency = db.Column(db.String(10), default="SAR")
    video_provider = db.Column(db.String(20), nullable=True)  # admin override: sora, veo, none (null=use plan default)
    account_type = db.Column(db.String(30), default="entrepreneur")  # entrepreneur, investor, factory, incubator, other
    interests_json = db.Column(db.JSON, nullable=True)  # sectors of interest
    company_name = db.Column(db.String(500), nullable=True)
    factory_partner_id = db.Column(db.Integer, db.ForeignKey("factory_partners.id"), nullable=True)
    referral_code = db.Column(db.String(20), unique=True, nullable=True)
    referred_by = db.Column(db.String(20), nullable=True)
    google_nlm_session_path = db.Column(db.String(500), nullable=True)
    google_nlm_connected_at = db.Column(db.DateTime, nullable=True)

    # Google OAuth fields
    google_id = db.Column(db.String(255), nullable=True, index=True)
    google_access_token = db.Column(db.Text, nullable=True)  # Encrypted
    google_refresh_token = db.Column(db.Text, nullable=True)  # Encrypted
    google_email = db.Column(db.String(255), nullable=True)
    auth_provider = db.Column(db.String(20), default="email")  # 'email', 'google', 'both'
    otp_code = db.Column(db.String(10), nullable=True)
    otp_expires_at = db.Column(db.DateTime, nullable=True)
    personal_email = db.Column(db.String(255), nullable=True)
    email_preference = db.Column(db.String(20), nullable=True)  # 'gmail' or 'personal'

    # Enterprise registration fields
    phone = db.Column(db.String(20), nullable=True)
    full_name = db.Column(db.String(255), nullable=True)
    industry_type = db.Column(db.String(50), nullable=True)
    company_size = db.Column(db.String(50), nullable=True)
    company_stage = db.Column(db.String(50), nullable=True)
    company_sector = db.Column(db.String(100), nullable=True)
    target_market = db.Column(db.String(100), nullable=True)
    budget_range = db.Column(db.String(50), nullable=True)
    activity_type = db.Column(db.String(50), nullable=True)
    is_active = db.Column(db.Boolean, default=True)
    is_suspended = db.Column(db.Boolean, default=False)
    suspended_at = db.Column(db.DateTime, nullable=True)
    suspended_by_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True)
    suspension_reason = db.Column(db.Text, nullable=True)
    deleted_at = db.Column(db.DateTime, nullable=True)
    deleted_by_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True)
    blocked_email = db.Column(db.String(255), nullable=True)  # Store original email when blocking

    organization_id = db.Column(db.Integer, db.ForeignKey("organizations.id"), nullable=True, index=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    reports = db.relationship("Report", backref="user", lazy="dynamic")
    subscription = db.relationship("Subscription", backref="user", uselist=False)

    # Self-referential relationships for suspension/deletion tracking
    suspended_by = db.relationship("User", foreign_keys=[suspended_by_id], remote_side=[id], lazy="select")
    deleted_by = db.relationship("User", foreign_keys=[deleted_by_id], remote_side=[id], lazy="select")

    @property
    def role(self):
        """Get user role based on is_admin flag."""
        if self.is_admin:
            return "admin"
        # Check if user email matches a trainer email
        from app.models.course import Trainer
        trainer = Trainer.query.filter_by(email=self.email).first()
        if trainer:
            return "trainer"
        return "student"

    @property
    def is_trainer(self):
        """Check if user is trainer."""
        return self.role == "trainer"

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        # Users without password (Google-only) cannot login with email/password
        if not self.password_hash:
            return False
        return check_password_hash(self.password_hash, password)

    def generate_token(self, purpose, expires_sec=3600):
        from itsdangerous import URLSafeTimedSerializer
        from flask import current_app
        s = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
        return s.dumps(self.email, salt=purpose)

    @staticmethod
    def verify_token(token, purpose, expires_sec=3600):
        from itsdangerous import URLSafeTimedSerializer, SignatureExpired, BadSignature
        from flask import current_app
        s = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
        try:
            email = s.loads(token, salt=purpose, max_age=expires_sec)
        except (SignatureExpired, BadSignature):
            return None
        return User.query.filter_by(email=email).first()

    @property
    def effective_video_provider(self):
        """User override → plan default → 'sora'."""
        if self.video_provider:
            return self.video_provider
        plan = self.active_plan
        if plan and plan.video_provider:
            return plan.video_provider
        return "sora"

    @property
    def active_plan(self):
        from app.models.subscription import Plan
        if self.subscription and self.subscription.status == "active":
            return self.subscription.plan
        return Plan.query.filter_by(name="free").first()

    @property
    def reports_this_month(self):
        from app.models.report import Report
        now = datetime.utcnow()
        start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        return self.reports.filter(Report.created_at >= start).count()

    @property
    def can_create_report(self):
        plan = self.active_plan
        if not plan:
            return False
        if plan.reports_per_month == -1:
            return True
        return self.reports_this_month < plan.reports_per_month

    @property
    def has_premium_access(self):
        """Check if user has premium subscription (Pro or Enterprise)."""
        plan = self.active_plan
        if not plan:
            return False
        return plan.name in ['pro', 'enterprise']


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))
