"""tenant onboarding: profile fields, memberships, domain verification, default plans

Revision ID: 0005_tenant_onboarding
Revises: 0004_user_sso_link
Create Date: 2026-07-07

این migration زیرساخت فاز Onboarding/Activation را اضافه می‌کند:
    - فیلدهای پروفایل/برندینگ و onboarding_completed روی tenants
    - مقادیر جدید چرخه عمر tenant_status (draft/pending_activation/archived)
    - ستون‌های is_primary و verification_status روی domains
    - جدول tenant_memberships (رابطه واقعی user <-> tenant)
    - ستون current_tenant_id روی users (tenant انتخابی جاری کاربر)
    - seed پلن‌های پیش‌فرض FREE و STARTER
"""
from __future__ import annotations

import uuid
from typing import Sequence, Union

import sqlalchemy as sa
from alembic import op

revision: str = "0005_tenant_onboarding"
down_revision: Union[str, None] = "0004_user_sso_link"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    bind = op.get_bind()
    is_postgres = bind.dialect.name == "postgresql"

    # ---- ۱) مقادیر جدید چرخه عمر tenant_status ----
    if is_postgres:
        for value in ("DRAFT", "PENDING_ACTIVATION", "ARCHIVED"):
            op.execute(f"ALTER TYPE tenant_status ADD VALUE IF NOT EXISTS '{value}'")

    # ---- ۲) پروفایل/برندینگ روی tenants ----
    op.add_column("tenants", sa.Column("business_type", sa.String(length=100), nullable=True))
    op.add_column(
        "tenants",
        sa.Column("default_locale", sa.String(length=20), nullable=False, server_default="fa-IR"),
    )
    op.add_column(
        "tenants",
        sa.Column("timezone", sa.String(length=50), nullable=False, server_default="Asia/Tehran"),
    )
    op.add_column("tenants", sa.Column("primary_color", sa.String(length=20), nullable=True))
    op.add_column("tenants", sa.Column("secondary_color", sa.String(length=20), nullable=True))
    op.add_column("tenants", sa.Column("logo_url", sa.String(length=500), nullable=True))
    op.add_column("tenants", sa.Column("favicon_url", sa.String(length=500), nullable=True))
    op.add_column(
        "tenants",
        sa.Column(
            "onboarding_completed", sa.Boolean(), nullable=False, server_default=sa.text("false")
        ),
    )
    op.alter_column("tenants", "default_locale", server_default=None)
    op.alter_column("tenants", "timezone", server_default=None)
    op.alter_column("tenants", "onboarding_completed", server_default=None)

    # ---- ۳) وضعیت تأیید دامنه ----
    domain_verification_status = sa.Enum(
        "pending", "verified", "failed", name="domain_verification_status"
    )
    domain_verification_status.create(bind, checkfirst=True)
    op.add_column(
        "domains", sa.Column("is_primary", sa.Boolean(), nullable=False, server_default=sa.text("false"))
    )
    op.add_column(
        "domains",
        sa.Column(
            "verification_status",
            domain_verification_status,
            nullable=False,
            server_default="pending",
        ),
    )
    op.execute("UPDATE domains SET verification_status = 'verified' WHERE is_verified = true")
    op.alter_column("domains", "is_primary", server_default=None)
    op.alter_column("domains", "verification_status", server_default=None)

    # ---- ۴) tenant انتخابی جاری کاربر ----
    op.add_column("users", sa.Column("current_tenant_id", sa.UUID(), nullable=True))
    op.create_foreign_key(
        "fk_users_current_tenant_id",
        "users",
        "tenants",
        ["current_tenant_id"],
        ["id"],
        ondelete="SET NULL",
    )

    # ---- ۵) جدول tenant_memberships ----
    op.create_table(
        "tenant_memberships",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("tenant_id", sa.UUID(), nullable=False),
        sa.Column("user_id", sa.UUID(), nullable=False),
        sa.Column(
            "role",
            sa.Enum(
                "platform_admin",
                "tenant_owner",
                "tenant_admin",
                "tenant_editor",
                "tenant_viewer",
                name="tenant_membership_role",
            ),
            nullable=False,
        ),
        sa.Column(
            "status",
            sa.Enum("active", "invited", "disabled", name="tenant_membership_status"),
            nullable=False,
        ),
        sa.Column("is_owner", sa.Boolean(), nullable=False, server_default=sa.text("false")),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False),
        sa.ForeignKeyConstraint(["tenant_id"], ["tenants.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("tenant_id", "user_id", name="uq_tenant_membership_tenant_user"),
    )
    op.create_index("ix_tenant_memberships_tenant_id", "tenant_memberships", ["tenant_id"])
    op.create_index("ix_tenant_memberships_user_id", "tenant_memberships", ["user_id"])
    op.create_index("ix_tenant_memberships_role", "tenant_memberships", ["role"])
    op.create_index("ix_tenant_memberships_status", "tenant_memberships", ["status"])
    op.alter_column("tenant_memberships", "is_owner", server_default=None)

    # ---- ۶) seed پلن‌های پیش‌فرض (idempotent — بر اساس code) ----
    op.execute(
        sa.text(
            """
            INSERT INTO plans (id, code, name, description, is_active)
            VALUES (CAST(:id AS uuid), 'FREE', 'رایگان', 'پلن پیش‌فرض onboarding — بدون هزینه', true)
            ON CONFLICT (code) DO NOTHING
            """
        ).bindparams(id=str(uuid.uuid4()))
    )
    op.execute(
        sa.text(
            """
            INSERT INTO plans (id, code, name, description, is_active)
            VALUES (CAST(:id AS uuid), 'STARTER', 'استارتر', 'پلن مقدماتی برای کسب‌وکارهای کوچک', true)
            ON CONFLICT (code) DO NOTHING
            """
        ).bindparams(id=str(uuid.uuid4()))
    )


def downgrade() -> None:
    bind = op.get_bind()

    op.execute("DELETE FROM plans WHERE code IN ('FREE', 'STARTER')")

    op.drop_index("ix_tenant_memberships_status", table_name="tenant_memberships")
    op.drop_index("ix_tenant_memberships_role", table_name="tenant_memberships")
    op.drop_index("ix_tenant_memberships_user_id", table_name="tenant_memberships")
    op.drop_index("ix_tenant_memberships_tenant_id", table_name="tenant_memberships")
    op.drop_table("tenant_memberships")
    op.execute("DROP TYPE IF EXISTS tenant_membership_status")
    op.execute("DROP TYPE IF EXISTS tenant_membership_role")

    op.drop_constraint("fk_users_current_tenant_id", "users", type_="foreignkey")
    op.drop_column("users", "current_tenant_id")

    op.drop_column("domains", "verification_status")
    op.drop_column("domains", "is_primary")
    sa.Enum(name="domain_verification_status").drop(bind, checkfirst=True)

    op.drop_column("tenants", "onboarding_completed")
    op.drop_column("tenants", "favicon_url")
    op.drop_column("tenants", "logo_url")
    op.drop_column("tenants", "secondary_color")
    op.drop_column("tenants", "primary_color")
    op.drop_column("tenants", "timezone")
    op.drop_column("tenants", "default_locale")
    op.drop_column("tenants", "business_type")

    # توجه: مقادیر جدید tenant_status (draft/pending_activation/archived) در
    # PostgreSQL قابل حذف مستقیم از نوع enum نیستند؛ در صورت نیاز باید نوع را
    # بازسازی کرد. در این downgrade نادیده گرفته می‌شود.