# app/modules/billing/migrations/versions/billing_001_merchant_subscriptions_and_feature_limits.py
"""
Merchant subscriptions and feature limits migration.

Creates:
- merchant_subscriptions table (replaces store_subscriptions)
- tier_feature_limits table (replaces hardcoded limit columns)
- merchant_feature_overrides table (replaces custom_*_limit columns)

Drops:
- store_subscriptions table
- features table

Alters:
- subscription_tiers: removes limit columns and features JSON

Revision ID: billing_001
"""

import sqlalchemy as sa

from alembic import op

# Revision identifiers
revision = "billing_001"
down_revision = None
branch_labels = ("billing",)
depends_on = None


def upgrade() -> None:
    # ========================================================================
    # Create merchant_subscriptions table
    # ========================================================================
    op.create_table(
        "merchant_subscriptions",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("merchant_id", sa.Integer(), sa.ForeignKey("merchants.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("platform_id", sa.Integer(), sa.ForeignKey("platforms.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("tier_id", sa.Integer(), sa.ForeignKey("subscription_tiers.id", ondelete="SET NULL"), nullable=True, index=True),
        sa.Column("status", sa.String(20), nullable=False, server_default="trial", index=True),
        sa.Column("is_annual", sa.Boolean(), nullable=False, server_default="0"),
        sa.Column("period_start", sa.DateTime(timezone=True), nullable=False),
        sa.Column("period_end", sa.DateTime(timezone=True), nullable=False),
        sa.Column("trial_ends_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("stripe_customer_id", sa.String(100), nullable=True, index=True),
        sa.Column("stripe_subscription_id", sa.String(100), nullable=True, index=True),
        sa.Column("stripe_payment_method_id", sa.String(100), nullable=True),
        sa.Column("payment_retry_count", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("last_payment_error", sa.Text(), nullable=True),
        sa.Column("cancelled_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("cancellation_reason", sa.Text(), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.UniqueConstraint("merchant_id", "platform_id", name="uq_merchant_platform_subscription"),
    )
    op.create_index("idx_merchant_sub_status", "merchant_subscriptions", ["merchant_id", "status"])
    op.create_index("idx_merchant_sub_platform", "merchant_subscriptions", ["platform_id", "status"])

    # ========================================================================
    # Create tier_feature_limits table
    # ========================================================================
    op.create_table(
        "tier_feature_limits",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("tier_id", sa.Integer(), sa.ForeignKey("subscription_tiers.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("feature_code", sa.String(80), nullable=False, index=True),
        sa.Column("limit_value", sa.Integer(), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.UniqueConstraint("tier_id", "feature_code", name="uq_tier_feature_code"),
    )
    op.create_index("idx_tier_feature_lookup", "tier_feature_limits", ["tier_id", "feature_code"])

    # ========================================================================
    # Create merchant_feature_overrides table
    # ========================================================================
    op.create_table(
        "merchant_feature_overrides",
        sa.Column("id", sa.Integer(), primary_key=True, index=True),
        sa.Column("merchant_id", sa.Integer(), sa.ForeignKey("merchants.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("platform_id", sa.Integer(), sa.ForeignKey("platforms.id", ondelete="CASCADE"), nullable=False, index=True),
        sa.Column("feature_code", sa.String(80), nullable=False, index=True),
        sa.Column("limit_value", sa.Integer(), nullable=True),
        sa.Column("is_enabled", sa.Boolean(), nullable=False, server_default="1"),
        sa.Column("reason", sa.String(255), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
        sa.UniqueConstraint("merchant_id", "platform_id", "feature_code", name="uq_merchant_platform_feature"),
    )
    op.create_index("idx_merchant_override_lookup", "merchant_feature_overrides", ["merchant_id", "platform_id", "feature_code"])

    # ========================================================================
    # Drop legacy tables
    # ========================================================================
    op.drop_table("store_subscriptions")
    op.drop_table("features")

    # ========================================================================
    # Remove legacy columns from subscription_tiers
    # ========================================================================
    with op.batch_alter_table("subscription_tiers") as batch_op:
        batch_op.drop_column("orders_per_month")
        batch_op.drop_column("products_limit")
        batch_op.drop_column("team_members")
        batch_op.drop_column("order_history_months")
        batch_op.drop_column("cms_pages_limit")
        batch_op.drop_column("cms_custom_pages_limit")
        batch_op.drop_column("features")

    # ========================================================================
    # Update stripe_webhook_events FK to merchant_subscriptions
    # ========================================================================
    with op.batch_alter_table("stripe_webhook_events") as batch_op:
        batch_op.drop_column("subscription_id")
        batch_op.add_column(
            sa.Column("merchant_subscription_id", sa.Integer(),
                       sa.ForeignKey("merchant_subscriptions.id"), nullable=True, index=True)
        )

    # ========================================================================
    # Add merchant_id to billing_history
    # ========================================================================
    with op.batch_alter_table("billing_history") as batch_op:
        batch_op.add_column(
            sa.Column("merchant_id", sa.Integer(),
                       sa.ForeignKey("merchants.id"), nullable=True, index=True)
        )


def downgrade() -> None:
    # Remove merchant_id from billing_history
    with op.batch_alter_table("billing_history") as batch_op:
        batch_op.drop_column("merchant_id")

    # Restore subscription_id on stripe_webhook_events
    with op.batch_alter_table("stripe_webhook_events") as batch_op:
        batch_op.drop_column("merchant_subscription_id")
        batch_op.add_column(
            sa.Column("subscription_id", sa.Integer(),
                       sa.ForeignKey("store_subscriptions.id"), nullable=True, index=True)
        )

    # Restore columns on subscription_tiers
    with op.batch_alter_table("subscription_tiers") as batch_op:
        batch_op.add_column(sa.Column("orders_per_month", sa.Integer(), nullable=True))
        batch_op.add_column(sa.Column("products_limit", sa.Integer(), nullable=True))
        batch_op.add_column(sa.Column("team_members", sa.Integer(), nullable=True))
        batch_op.add_column(sa.Column("order_history_months", sa.Integer(), nullable=True))
        batch_op.add_column(sa.Column("cms_pages_limit", sa.Integer(), nullable=True))
        batch_op.add_column(sa.Column("cms_custom_pages_limit", sa.Integer(), nullable=True))
        batch_op.add_column(sa.Column("features", sa.JSON(), nullable=True))

    # Recreate features table
    op.create_table(
        "features",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("code", sa.String(50), unique=True, nullable=False),
        sa.Column("name", sa.String(100), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("category", sa.String(50), nullable=False),
        sa.Column("is_active", sa.Boolean(), server_default="1"),
    )

    # Recreate store_subscriptions table
    op.create_table(
        "store_subscriptions",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("store_id", sa.Integer(), sa.ForeignKey("stores.id"), unique=True, nullable=False),
        sa.Column("tier", sa.String(20), nullable=False, server_default="essential"),
        sa.Column("status", sa.String(20), nullable=False, server_default="trial"),
        sa.Column("period_start", sa.DateTime(timezone=True), nullable=False),
        sa.Column("period_end", sa.DateTime(timezone=True), nullable=False),
    )

    # Drop new tables
    op.drop_table("merchant_feature_overrides")
    op.drop_table("tier_feature_limits")
    op.drop_table("merchant_subscriptions")
