import uuid
from datetime import datetime, timezone

from sqlalchemy import (
    Column,
    String,
    Integer,
    BigInteger,
    Boolean,
    DateTime,
    Text,
    ForeignKey,
    Index,
)
from sqlalchemy.orm import relationship

from database import Base


def gen_uuid():
    return str(uuid.uuid4())


def utcnow():
    return datetime.now(timezone.utc)


class User(Base):
    __tablename__ = "users"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    email = Column(String(255), unique=True, nullable=False, index=True)
    password_hash = Column(String(255), nullable=False)
    name = Column(String(120), nullable=False, default="User")
    role = Column(String(20), nullable=False, default="user")
    totp_secret = Column(String(64), nullable=True)
    totp_enabled = Column(Boolean, default=False)
    is_active = Column(Boolean, default=True)     # admin can disable an account without deleting it
    avatar_color = Column(String(20), nullable=True)  # for a default colored-initial profile icon
    created_at = Column(DateTime, default=utcnow)

    migrations = relationship("Migration", back_populates="owner", cascade="all, delete-orphan")


class Migration(Base):
    __tablename__ = "migrations"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
    name = Column(String(200), nullable=False)

    source_host = Column(String(255), nullable=False)
    source_port = Column(Integer, nullable=False, default=993)
    source_email = Column(String(255), nullable=False)
    source_password_enc = Column(Text, nullable=True)
    source_ssl = Column(Boolean, default=True)
    source_auth_method = Column(String(10), nullable=False, default="password")  # password | oauth
    source_oauth_provider = Column(String(20), nullable=True)  # google | microsoft
    source_refresh_token_enc = Column(Text, nullable=True)

    dest_host = Column(String(255), nullable=False)
    dest_port = Column(Integer, nullable=False, default=993)
    dest_email = Column(String(255), nullable=False)
    dest_password_enc = Column(Text, nullable=True)
    dest_ssl = Column(Boolean, default=True)
    dest_auth_method = Column(String(10), nullable=False, default="password")
    dest_oauth_provider = Column(String(20), nullable=True)
    dest_refresh_token_enc = Column(Text, nullable=True)

    # pending | scheduled | queued | running | completed | failed | paused
    status = Column(String(20), nullable=False, default="pending", index=True)

    scheduled_at = Column(DateTime, nullable=True)
    selected_folders = Column(Text, nullable=True)   # JSON list of source folders; null = all
    recurring = Column(Boolean, default=False)
    recurring_minutes = Column(Integer, nullable=True)
    next_run_at = Column(DateTime, nullable=True)
    date_from = Column(DateTime, nullable=True)
    date_to = Column(DateTime, nullable=True)

    total_emails = Column(Integer, default=0)
    migrated_emails = Column(Integer, default=0)
    failed_emails = Column(Integer, default=0)
    total_folders = Column(Integer, default=0)
    migrated_folders = Column(Integer, default=0)
    bytes_transferred = Column(BigInteger, default=0)

    error = Column(Text, nullable=True)

    created_at = Column(DateTime, default=utcnow)
    started_at = Column(DateTime, nullable=True)
    completed_at = Column(DateTime, nullable=True)

    owner = relationship("User", back_populates="migrations")
    folders = relationship("MigrationFolder", back_populates="migration", cascade="all, delete-orphan")
    logs = relationship("MigrationLog", back_populates="migration", cascade="all, delete-orphan")


class MigrationFolder(Base):
    __tablename__ = "migration_folders"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    migration_id = Column(String(36), ForeignKey("migrations.id"), nullable=False, index=True)
    name = Column(String(500), nullable=False)
    total = Column(Integer, default=0)
    migrated = Column(Integer, default=0)
    status = Column(String(20), default="pending")

    migration = relationship("Migration", back_populates="folders")


class MigrationLog(Base):
    __tablename__ = "migration_logs"

    id = Column(Integer, primary_key=True, autoincrement=True)
    migration_id = Column(String(36), ForeignKey("migrations.id"), nullable=False, index=True)
    ts = Column(DateTime, default=utcnow)
    level = Column(String(10), default="info")
    message = Column(Text, nullable=False)

    migration = relationship("Migration", back_populates="logs")


Index("ix_logs_mig_id_id", MigrationLog.migration_id, MigrationLog.id)


class Package(Base):
    __tablename__ = "packages"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    name = Column(String(120), nullable=False)
    description = Column(Text, nullable=True)
    price = Column(Integer, default=0)            # in paise (INR)
    currency = Column(String(10), default="INR")
    max_migrations = Column(Integer, default=10)  # -1 = unlimited
    storage_per_mailbox_gb = Column(Integer, default=50)
    storage_mb = Column(Integer, nullable=True)  # precise MB value; takes precedence over the GB field when set
    max_mailboxes = Column(Integer, default=-1)   # -1 = unlimited
    validity_days = Column(Integer, default=30)
    is_active = Column(Boolean, default=True)
    sort_order = Column(Integer, default=0)
    created_at = Column(DateTime, default=utcnow)


class Subscription(Base):
    __tablename__ = "subscriptions"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
    package_id = Column(String(36), ForeignKey("packages.id"), nullable=True)
    package_name = Column(String(120), nullable=True)
    status = Column(String(20), default="pending")  # pending | active | expired
    migrations_used = Column(Integer, default=0)
    max_migrations = Column(Integer, default=10)
    max_mailboxes = Column(Integer, default=-1)
    storage_per_mailbox_gb = Column(Integer, default=50)
    amount = Column(Integer, default=0)
    storage_mb = Column(Integer, nullable=True)
    coupon_code = Column(String(40), nullable=True)
    razorpay_order_id = Column(String(80), nullable=True)
    razorpay_payment_id = Column(String(80), nullable=True)
    starts_at = Column(DateTime, nullable=True)
    expires_at = Column(DateTime, nullable=True)
    expiry_notified = Column(Boolean, default=False)
    created_at = Column(DateTime, default=utcnow)


class SiteSetting(Base):
    __tablename__ = "site_settings"

    id = Column(String(20), primary_key=True, default="main")
    site_name = Column(String(120), default="MailShift")
    tagline = Column(String(255), default="Fast, reliable email migration")
    logo_url = Column(Text, nullable=True)
    brand_color = Column(String(20), default="#2563EB")
    hero_title = Column(String(255), default="Migrate mailboxes directly, provider to provider")
    hero_subtitle = Column(Text, default="Bulk IMAP migrations with real-time progress, folder mapping and live logs.")
    pricing_title = Column(String(255), default="Simple, transparent pricing")
    pricing_subtitle = Column(Text, default="Choose a plan that fits your migration needs.")
    contact_email = Column(String(255), default="support@mailshift.com")
    footer_text = Column(Text, default="© MailShift. All rights reserved.")
    updated_at = Column(DateTime, default=utcnow)


class LoginLockout(Base):
    __tablename__ = "login_lockouts"

    identifier = Column(String(255), primary_key=True)
    fail_count = Column(Integer, default=0)
    locked_until = Column(DateTime, nullable=True)
    updated_at = Column(DateTime, default=utcnow)


class Coupon(Base):
    __tablename__ = "coupons"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    code = Column(String(40), unique=True, nullable=False, index=True)
    percent_off = Column(Integer, default=10)
    active = Column(Boolean, default=True)
    max_redemptions = Column(Integer, nullable=True)
    times_used = Column(Integer, default=0)
    expires_at = Column(DateTime, nullable=True)
    created_at = Column(DateTime, default=utcnow)


class CloudAccount(Base):
    __tablename__ = "cloud_accounts"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
    provider = Column(String(20), nullable=False)   # google | microsoft
    email = Column(String(255), nullable=False)
    access_token_enc = Column(Text, nullable=True)
    refresh_token_enc = Column(Text, nullable=True)
    expires_at = Column(DateTime, nullable=True)
    created_at = Column(DateTime, default=utcnow)


class CloudMigration(Base):
    __tablename__ = "cloud_migrations"

    id = Column(String(36), primary_key=True, default=gen_uuid)
    user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
    name = Column(String(200), nullable=False)
    kind = Column(String(20), default="files")      # files | contacts
    source_account_id = Column(String(36), nullable=False)
    dest_account_id = Column(String(36), nullable=False)
    status = Column(String(20), default="pending")
    total = Column(Integer, default=0)
    migrated = Column(Integer, default=0)
    failed = Column(Integer, default=0)
    bytes_transferred = Column(BigInteger, default=0)
    logs = Column(Text, nullable=True)
    error = Column(Text, nullable=True)
    created_at = Column(DateTime, default=utcnow)
    started_at = Column(DateTime, nullable=True)
    completed_at = Column(DateTime, nullable=True)


class AppSetting(Base):
    """Key-value store for admin-managed integration keys (OAuth/Razorpay). Values encrypted at rest."""
    __tablename__ = "app_settings"

    key = Column(String(80), primary_key=True)
    value = Column(Text, nullable=True)
    updated_at = Column(DateTime, default=utcnow)


class EmailTemplate(Base):
    """Admin-editable transactional email templates. 'key' is the fixed event
    identifier the code looks up (e.g. 'welcome'); subject/body support {{variable}}
    placeholders that get substituted per-send."""
    __tablename__ = "email_templates"

    key = Column(String(60), primary_key=True)
    name = Column(String(120), nullable=False)          # human label shown in admin UI
    description = Column(String(255), nullable=True)     # when this email is sent + available variables
    subject = Column(String(255), nullable=False)
    body_text = Column(Text, nullable=False)
    body_html = Column(Text, nullable=True)
    is_active = Column(Boolean, default=True)
    updated_at = Column(DateTime, default=utcnow, onupdate=utcnow)


class PasswordResetToken(Base):
    __tablename__ = "password_reset_tokens"

    token = Column(String(64), primary_key=True)
    user_id = Column(String(36), nullable=False)
    expires_at = Column(DateTime, nullable=False)
    used = Column(Boolean, default=False)
    created_at = Column(DateTime, default=utcnow)
