"""SQLAlchemy ORM models for the WHM/cPanel Reseller Manager module.

All monetary values are kept as strings/Decimals via plain numeric columns
so the admin UI can format them without rounding surprises.  Tokens and
passwords are always stored encrypted (``mask_crypto``); callers must
never dump these fields to API responses.
"""
from __future__ import annotations

from sqlalchemy import (
    Boolean,
    Column,
    DateTime,
    ForeignKey,
    Integer,
    Numeric,
    String,
    Text,
    UniqueConstraint,
    func,
)

from core.database import Base


class CpanelServer(Base):
    """A WHM server end-point that we provision cPanel accounts on."""

    __tablename__ = "cpanel_servers"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(120), nullable=False, unique=True)
    hostname = Column(String(255), nullable=False)
    port = Column(Integer, nullable=False, default=2087)
    username = Column(String(120), nullable=False, default="root")
    encrypted_api_token = Column(Text, nullable=False)
    verify_tls = Column(Boolean, nullable=False, default=True)
    is_active = Column(Boolean, nullable=False, default=True)
    notes = Column(Text, nullable=True)

    last_tested_at = Column(DateTime(timezone=True), nullable=True)
    last_test_status = Column(String(32), nullable=True)  # ok | failed
    last_test_message = Column(Text, nullable=True)

    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime(timezone=True),
        server_default=func.now(),
        onupdate=func.now(),
        nullable=False,
    )


class CpanelPackage(Base):
    """A DoItEasy hosting plan mapped to a WHM package."""

    __tablename__ = "cpanel_packages"
    __table_args__ = (UniqueConstraint("server_id", "whm_package_name", name="uq_cpanel_pkg_server_name"),)

    id = Column(Integer, primary_key=True, index=True)
    server_id = Column(Integer, ForeignKey("cpanel_servers.id", ondelete="CASCADE"), nullable=False, index=True)

    # What admins see in DoItEasy
    display_name = Column(String(150), nullable=False)
    slug = Column(String(150), nullable=False, unique=True, index=True)
    description = Column(Text, nullable=True)
    monthly_price = Column(Numeric(10, 2), nullable=False, default=0)
    currency = Column(String(8), nullable=False, default="USD")

    # WHMCS + WHM mapping
    whmcs_product_id = Column(Integer, nullable=True, index=True)
    whm_package_name = Column(String(150), nullable=False)

    # Limits (cached from WHM listpkgs; editable by admin for display)
    disk_quota_mb = Column(Integer, nullable=True)
    bandwidth_mb = Column(Integer, nullable=True)
    max_email_accounts = Column(Integer, nullable=True)
    max_ftp_accounts = Column(Integer, nullable=True)
    max_databases = Column(Integer, nullable=True)
    max_subdomains = Column(Integer, nullable=True)
    max_addon_domains = Column(Integer, nullable=True)
    max_parked_domains = Column(Integer, nullable=True)

    # Feature toggles
    has_ssl = Column(Boolean, nullable=False, default=True)
    has_backup = Column(Boolean, nullable=False, default=True)
    has_ssh = Column(Boolean, nullable=False, default=False)
    has_wordpress_tools = Column(Boolean, nullable=False, default=True)
    has_cloudlinux = Column(Boolean, nullable=False, default=False)

    # Resource limits (when CloudLinux/Selector is present)
    cpu_limit_percent = Column(Integer, nullable=True)
    memory_limit_mb = Column(Integer, nullable=True)
    io_limit_kbps = Column(Integer, nullable=True)
    iops_limit = Column(Integer, nullable=True)
    ep_limit = Column(Integer, nullable=True)
    nproc_limit = Column(Integer, nullable=True)

    is_active = Column(Boolean, nullable=False, default=True)
    sort_order = Column(Integer, nullable=False, default=0)

    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime(timezone=True),
        server_default=func.now(),
        onupdate=func.now(),
        nullable=False,
    )


class CpanelClientAccount(Base):
    """One provisioned cPanel hosting account for a DoItEasy user."""

    __tablename__ = "cpanel_client_accounts"
    __table_args__ = (
        UniqueConstraint("server_id", "cpanel_username", name="uq_cpanel_acct_server_user"),
    )

    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(String(255), nullable=False, index=True)
    server_id = Column(Integer, ForeignKey("cpanel_servers.id", ondelete="RESTRICT"), nullable=False, index=True)
    package_id = Column(Integer, ForeignKey("cpanel_packages.id", ondelete="SET NULL"), nullable=True, index=True)

    # WHMCS linkage (optional — supports orphan accounts)
    whmcs_service_id = Column(Integer, nullable=True, index=True)
    whmcs_client_id = Column(Integer, nullable=True, index=True)

    # cPanel identity
    cpanel_username = Column(String(120), nullable=False, index=True)
    main_domain = Column(String(255), nullable=False)
    contact_email = Column(String(255), nullable=True)
    encrypted_password = Column(Text, nullable=True)

    # Lifecycle
    status = Column(String(32), nullable=False, default="pending")
    # pending | active | suspended | terminated | failed
    suspend_reason = Column(String(255), nullable=True)
    last_error = Column(Text, nullable=True)

    # Timestamps for lifecycle events
    provisioned_at = Column(DateTime(timezone=True), nullable=True)
    suspended_at = Column(DateTime(timezone=True), nullable=True)
    unsuspended_at = Column(DateTime(timezone=True), nullable=True)
    terminated_at = Column(DateTime(timezone=True), nullable=True)

    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime(timezone=True),
        server_default=func.now(),
        onupdate=func.now(),
        nullable=False,
    )


class CpanelAccountUsage(Base):
    """Point-in-time usage snapshot for a cPanel account."""

    __tablename__ = "cpanel_account_usage"

    id = Column(Integer, primary_key=True, index=True)
    account_id = Column(
        Integer,
        ForeignKey("cpanel_client_accounts.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        unique=True,
    )

    disk_used_mb = Column(Integer, nullable=True)
    disk_limit_mb = Column(Integer, nullable=True)
    bandwidth_used_mb = Column(Integer, nullable=True)
    bandwidth_limit_mb = Column(Integer, nullable=True)

    email_accounts = Column(Integer, nullable=True)
    ftp_accounts = Column(Integer, nullable=True)
    databases = Column(Integer, nullable=True)
    subdomains = Column(Integer, nullable=True)
    addon_domains = Column(Integer, nullable=True)

    ssl_status = Column(String(32), nullable=True)  # active | expired | none
    backup_status = Column(String(32), nullable=True)  # ok | stale | none

    # CloudLinux / resource metrics (all nullable)
    cpu_used_percent = Column(Integer, nullable=True)
    memory_used_mb = Column(Integer, nullable=True)
    entry_processes = Column(Integer, nullable=True)

    last_synced_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)


class CpanelApiLog(Base):
    """Masked record of WHM/cPanel API calls for diagnostics."""

    __tablename__ = "cpanel_api_logs"

    id = Column(Integer, primary_key=True, index=True)
    server_id = Column(Integer, ForeignKey("cpanel_servers.id", ondelete="SET NULL"), nullable=True, index=True)
    account_id = Column(
        Integer,
        ForeignKey("cpanel_client_accounts.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )

    endpoint = Column(String(255), nullable=False)
    method = Column(String(16), nullable=False, default="GET")
    status = Column(String(32), nullable=False, default="ok")  # ok | failed
    http_status = Column(Integer, nullable=True)
    duration_ms = Column(Integer, nullable=True)
    request_preview = Column(Text, nullable=True)
    response_preview = Column(Text, nullable=True)
    error_message = Column(Text, nullable=True)

    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, index=True)


class CpanelAuditLog(Base):
    """Admin-performed lifecycle events (create/suspend/terminate/...)."""

    __tablename__ = "cpanel_audit_logs"

    id = Column(Integer, primary_key=True, index=True)
    action = Column(String(80), nullable=False, index=True)
    admin_user_id = Column(String(255), nullable=True, index=True)
    admin_email = Column(String(255), nullable=True)
    account_id = Column(
        Integer,
        ForeignKey("cpanel_client_accounts.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )
    target_user_id = Column(String(255), nullable=True, index=True)
    details = Column(Text, nullable=True)

    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, index=True)