import enum

from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, String, Text
from sqlalchemy import Enum as SAEnum
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.types import JSON

from app.models.base import BaseModel


class InstanceStatus(str, enum.Enum):
    PROVISIONING = "provisioning"       # 开通中
    ACTIVE = "active"                   # 运行中
    SUSPENDED = "suspended"             # 已暂停（流量超额/到期）
    TERMINATED = "terminated"           # 已销毁
    FAILED = "failed"                   # 开通失败（已退款）
    PROVISION_FAILED = "provision_failed"  # 自动开通失败（待人工处理，未退款）


class SuspendType(str, enum.Enum):
    TRAFFIC = "traffic"   # 流量超额
    DUE = "due"           # 到期暂停
    MANUAL = "manual"     # 人工暂停


class Instance(BaseModel):
    """云服务器实例。订单支付后每台服务器生成一条记录，跟踪开通状态和计费周期。"""

    __tablename__ = "instances"

    # ── 关联 ──────────────────────────────────────────────────────────────────
    user_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
    )
    order_id: Mapped[int] = mapped_column(
        ForeignKey("orders.id", ondelete="RESTRICT"), nullable=False, index=True
    )
    product_id: Mapped[int] = mapped_column(
        ForeignKey("products.id", ondelete="RESTRICT"), nullable=False, index=True
    )
    cloud_server_id: Mapped[int | None] = mapped_column(
        ForeignKey("cloud_servers.id", ondelete="SET NULL"), nullable=True, index=True
    )

    # ── 业务状态 ──────────────────────────────────────────────────────────────
    status: Mapped[InstanceStatus] = mapped_column(
        SAEnum(InstanceStatus, values_callable=lambda e: [m.value for m in e]),
        default=InstanceStatus.PROVISIONING,
        nullable=False,
        index=True,
    )
    suspend_type: Mapped[SuspendType | None] = mapped_column(
        SAEnum(SuspendType, values_callable=lambda e: [m.value for m in e]),
        nullable=True,
    )
    is_locked: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="是否锁定 0=否 1=是")
    internet: Mapped[int] = mapped_column(Integer, default=1, nullable=False, comment="网络状态 0=断网 1=正常")

    # ── 计费与周期 ────────────────────────────────────────────────────────────
    cycle: Mapped[str] = mapped_column(String(16), nullable=False, comment="计费周期 monthly/yearly 等")
    unit_price: Mapped[int] = mapped_column(Integer, nullable=False, comment="周期单价，单位分")
    expires_at: Mapped[DateTime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
    auto_renew: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="自动续费 0=否 1=是")
    next_renew_amount: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="下次续费金额，单位分")

    # ── 用户自定义 ────────────────────────────────────────────────────────────
    alias: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="用户备注名")
    hostname: Mapped[str | None] = mapped_column(String(64), nullable=True)
    os_image: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="操作系统镜像标识")

    # ── 硬件规格（冗余，续费/展示用）────────────────────────────────────────
    cpu: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="CPU 核心数")
    memory: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="内存 MB")
    system_disk_size: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="系统盘 GB")
    data_disk_size: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="数据盘 GB")
    in_bw: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="进带宽 Mbps")
    out_bw: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="出带宽 Mbps")
    ip_num: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="IP 数量")
    nat_acl_limit: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="NAT 转发数量限制")
    traffic_quota: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="流量限额 GB")
    traffic_type: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="流量统计方向 1=进 2=出 3=总计")

    # ── 魔方云上游 ────────────────────────────────────────────────────────────
    upstream_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True, comment="魔方云实例 ID")
    upstream_task_id: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="创建任务 ID，用于轮询进度")
    downstream_token: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
    upstream_invoice_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True)
    upstream_payload: Mapped[dict | list | None] = mapped_column(JSON, nullable=True)
    main_ip: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="主 IP 地址")
    root_password: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="AES-GCM 加密的 root 密码")
    ssh_port: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="SSH 端口")

    # ── 开通追踪 ──────────────────────────────────────────────────────────────
    provision_attempts: Mapped[int] = mapped_column(Integer, default=0, nullable=False, comment="开通尝试次数")
    last_provision_at: Mapped[DateTime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    provision_log: Mapped[str | None] = mapped_column(Text, nullable=True, comment="开通日志，失败时排查用")

    # ── 时间 ──────────────────────────────────────────────────────────────────
    terminated_at: Mapped[DateTime | None] = mapped_column(DateTime(timezone=True), nullable=True)
