"""add_subscription_billing_tables

Revision ID: 2953ed10d22c
Revises: e1bfb453fbe9
Create Date: 2025-12-25 18:29:34.167773

"""
from collections.abc import Sequence
from datetime import datetime

import sqlalchemy as sa

from alembic import op

# Removed: from sqlalchemy.dialects import sqlite (using sa.JSON for PostgreSQL)

# revision identifiers, used by Alembic.
revision: str = "2953ed10d22c"
down_revision: str | None = "e1bfb453fbe9"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
    # =========================================================================
    # Create new subscription and billing tables
    # =========================================================================

    # subscription_tiers - Database-driven tier definitions
    op.create_table("subscription_tiers",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("code", sa.String(length=30), nullable=False),
        sa.Column("name", sa.String(length=100), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("price_monthly_cents", sa.Integer(), nullable=False),
        sa.Column("price_annual_cents", sa.Integer(), nullable=True),
        sa.Column("orders_per_month", sa.Integer(), nullable=True),
        sa.Column("products_limit", sa.Integer(), nullable=True),
        sa.Column("team_members", sa.Integer(), nullable=True),
        sa.Column("order_history_months", sa.Integer(), nullable=True),
        sa.Column("features", sa.JSON(), nullable=True),
        sa.Column("stripe_product_id", sa.String(length=100), nullable=True),
        sa.Column("stripe_price_monthly_id", sa.String(length=100), nullable=True),
        sa.Column("stripe_price_annual_id", sa.String(length=100), nullable=True),
        sa.Column("display_order", sa.Integer(), nullable=True),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("is_public", sa.Boolean(), nullable=False),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index(op.f("ix_subscription_tiers_code"), "subscription_tiers", ["code"], unique=True)
    op.create_index(op.f("ix_subscription_tiers_id"), "subscription_tiers", ["id"], unique=False)

    # addon_products - Purchasable add-ons (domains, SSL, email)
    op.create_table("addon_products",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("code", sa.String(length=50), nullable=False),
        sa.Column("name", sa.String(length=100), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("category", sa.String(length=50), nullable=False),
        sa.Column("price_cents", sa.Integer(), nullable=False),
        sa.Column("billing_period", sa.String(length=20), nullable=False),
        sa.Column("quantity_unit", sa.String(length=50), nullable=True),
        sa.Column("quantity_value", sa.Integer(), nullable=True),
        sa.Column("stripe_product_id", sa.String(length=100), nullable=True),
        sa.Column("stripe_price_id", sa.String(length=100), nullable=True),
        sa.Column("display_order", sa.Integer(), nullable=True),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index(op.f("ix_addon_products_category"), "addon_products", ["category"], unique=False)
    op.create_index(op.f("ix_addon_products_code"), "addon_products", ["code"], unique=True)
    op.create_index(op.f("ix_addon_products_id"), "addon_products", ["id"], unique=False)

    # billing_history - Invoice and payment history
    op.create_table("billing_history",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("vendor_id", sa.Integer(), nullable=False),
        sa.Column("stripe_invoice_id", sa.String(length=100), nullable=True),
        sa.Column("stripe_payment_intent_id", sa.String(length=100), nullable=True),
        sa.Column("invoice_number", sa.String(length=50), nullable=True),
        sa.Column("invoice_date", sa.DateTime(timezone=True), nullable=False),
        sa.Column("due_date", sa.DateTime(timezone=True), nullable=True),
        sa.Column("subtotal_cents", sa.Integer(), nullable=False),
        sa.Column("tax_cents", sa.Integer(), nullable=False),
        sa.Column("total_cents", sa.Integer(), nullable=False),
        sa.Column("amount_paid_cents", sa.Integer(), nullable=False),
        sa.Column("currency", sa.String(length=3), nullable=False),
        sa.Column("status", sa.String(length=20), nullable=False),
        sa.Column("invoice_pdf_url", sa.String(length=500), nullable=True),
        sa.Column("hosted_invoice_url", sa.String(length=500), nullable=True),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("line_items", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"], ),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index("idx_billing_status", "billing_history", ["vendor_id", "status"], unique=False)
    op.create_index("idx_billing_vendor_date", "billing_history", ["vendor_id", "invoice_date"], unique=False)
    op.create_index(op.f("ix_billing_history_id"), "billing_history", ["id"], unique=False)
    op.create_index(op.f("ix_billing_history_status"), "billing_history", ["status"], unique=False)
    op.create_index(op.f("ix_billing_history_stripe_invoice_id"), "billing_history", ["stripe_invoice_id"], unique=True)
    op.create_index(op.f("ix_billing_history_vendor_id"), "billing_history", ["vendor_id"], unique=False)

    # vendor_addons - Add-ons purchased by vendor
    op.create_table("vendor_addons",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("vendor_id", sa.Integer(), nullable=False),
        sa.Column("addon_product_id", sa.Integer(), nullable=False),
        sa.Column("status", sa.String(length=20), nullable=False),
        sa.Column("domain_name", sa.String(length=255), nullable=True),
        sa.Column("quantity", sa.Integer(), nullable=False),
        sa.Column("stripe_subscription_item_id", sa.String(length=100), nullable=True),
        sa.Column("period_start", sa.DateTime(timezone=True), nullable=True),
        sa.Column("period_end", sa.DateTime(timezone=True), nullable=True),
        sa.Column("cancelled_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["addon_product_id"], ["addon_products.id"], ),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"], ),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index("idx_vendor_addon_product", "vendor_addons", ["vendor_id", "addon_product_id"], unique=False)
    op.create_index("idx_vendor_addon_status", "vendor_addons", ["vendor_id", "status"], unique=False)
    op.create_index(op.f("ix_vendor_addons_addon_product_id"), "vendor_addons", ["addon_product_id"], unique=False)
    op.create_index(op.f("ix_vendor_addons_domain_name"), "vendor_addons", ["domain_name"], unique=False)
    op.create_index(op.f("ix_vendor_addons_id"), "vendor_addons", ["id"], unique=False)
    op.create_index(op.f("ix_vendor_addons_status"), "vendor_addons", ["status"], unique=False)
    op.create_index(op.f("ix_vendor_addons_vendor_id"), "vendor_addons", ["vendor_id"], unique=False)

    # stripe_webhook_events - Webhook idempotency tracking
    op.create_table("stripe_webhook_events",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("event_id", sa.String(length=100), nullable=False),
        sa.Column("event_type", sa.String(length=100), nullable=False),
        sa.Column("status", sa.String(length=20), nullable=False),
        sa.Column("processed_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("error_message", sa.Text(), nullable=True),
        sa.Column("payload_encrypted", sa.Text(), nullable=True),
        sa.Column("vendor_id", sa.Integer(), nullable=True),
        sa.Column("subscription_id", sa.Integer(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["subscription_id"], ["vendor_subscriptions.id"], ),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"], ),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index("idx_webhook_event_type_status", "stripe_webhook_events", ["event_type", "status"], unique=False)
    op.create_index(op.f("ix_stripe_webhook_events_event_id"), "stripe_webhook_events", ["event_id"], unique=True)
    op.create_index(op.f("ix_stripe_webhook_events_event_type"), "stripe_webhook_events", ["event_type"], unique=False)
    op.create_index(op.f("ix_stripe_webhook_events_id"), "stripe_webhook_events", ["id"], unique=False)
    op.create_index(op.f("ix_stripe_webhook_events_status"), "stripe_webhook_events", ["status"], unique=False)
    op.create_index(op.f("ix_stripe_webhook_events_subscription_id"), "stripe_webhook_events", ["subscription_id"], unique=False)
    op.create_index(op.f("ix_stripe_webhook_events_vendor_id"), "stripe_webhook_events", ["vendor_id"], unique=False)

    # =========================================================================
    # Add new columns to vendor_subscriptions
    # =========================================================================
    op.add_column("vendor_subscriptions", sa.Column("stripe_price_id", sa.String(length=100), nullable=True))
    op.add_column("vendor_subscriptions", sa.Column("stripe_payment_method_id", sa.String(length=100), nullable=True))
    op.add_column("vendor_subscriptions", sa.Column("proration_behavior", sa.String(length=50), nullable=True))
    op.add_column("vendor_subscriptions", sa.Column("scheduled_tier_change", sa.String(length=30), nullable=True))
    op.add_column("vendor_subscriptions", sa.Column("scheduled_change_at", sa.DateTime(timezone=True), nullable=True))
    op.add_column("vendor_subscriptions", sa.Column("payment_retry_count", sa.Integer(), server_default="0", nullable=False))
    op.add_column("vendor_subscriptions", sa.Column("last_payment_error", sa.Text(), nullable=True))

    # =========================================================================
    # Seed subscription tiers
    # =========================================================================
    now = datetime.utcnow()

    subscription_tiers = sa.table(
        "subscription_tiers",
        sa.column("code", sa.String),
        sa.column("name", sa.String),
        sa.column("description", sa.Text),
        sa.column("price_monthly_cents", sa.Integer),
        sa.column("price_annual_cents", sa.Integer),
        sa.column("orders_per_month", sa.Integer),
        sa.column("products_limit", sa.Integer),
        sa.column("team_members", sa.Integer),
        sa.column("order_history_months", sa.Integer),
        sa.column("features", sa.JSON),
        sa.column("display_order", sa.Integer),
        sa.column("is_active", sa.Boolean),
        sa.column("is_public", sa.Boolean),
        sa.column("created_at", sa.DateTime),
        sa.column("updated_at", sa.DateTime),
    )

    op.bulk_insert(subscription_tiers, [
        {
            "code": "essential",
            "name": "Essential",
            "description": "Perfect for solo vendors getting started with Letzshop",
            "price_monthly_cents": 4900,
            "price_annual_cents": 49000,
            "orders_per_month": 100,
            "products_limit": 200,
            "team_members": 1,
            "order_history_months": 6,
            "features": ["letzshop_sync", "inventory_basic", "invoice_lu", "customer_view"],
            "display_order": 1,
            "is_active": True,
            "is_public": True,
            "created_at": now,
            "updated_at": now,
        },
        {
            "code": "professional",
            "name": "Professional",
            "description": "For active multi-channel vendors shipping EU-wide",
            "price_monthly_cents": 9900,
            "price_annual_cents": 99000,
            "orders_per_month": 500,
            "products_limit": None,
            "team_members": 3,
            "order_history_months": 24,
            "features": [
                "letzshop_sync", "inventory_locations", "inventory_purchase_orders",
                "invoice_lu", "invoice_eu_vat", "customer_view", "customer_export"
            ],
            "display_order": 2,
            "is_active": True,
            "is_public": True,
            "created_at": now,
            "updated_at": now,
        },
        {
            "code": "business",
            "name": "Business",
            "description": "For high-volume vendors with teams and data-driven operations",
            "price_monthly_cents": 19900,
            "price_annual_cents": 199000,
            "orders_per_month": 2000,
            "products_limit": None,
            "team_members": 10,
            "order_history_months": None,
            "features": [
                "letzshop_sync", "inventory_locations", "inventory_purchase_orders",
                "invoice_lu", "invoice_eu_vat", "invoice_bulk", "customer_view",
                "customer_export", "analytics_dashboard", "accounting_export",
                "api_access", "automation_rules", "team_roles"
            ],
            "display_order": 3,
            "is_active": True,
            "is_public": True,
            "created_at": now,
            "updated_at": now,
        },
        {
            "code": "enterprise",
            "name": "Enterprise",
            "description": "Custom solutions for large operations and agencies",
            "price_monthly_cents": 39900,
            "price_annual_cents": None,
            "orders_per_month": None,
            "products_limit": None,
            "team_members": None,
            "order_history_months": None,
            "features": [
                "letzshop_sync", "inventory_locations", "inventory_purchase_orders",
                "invoice_lu", "invoice_eu_vat", "invoice_bulk", "customer_view",
                "customer_export", "analytics_dashboard", "accounting_export",
                "api_access", "automation_rules", "team_roles", "white_label",
                "multi_vendor", "custom_integrations", "sla_guarantee", "dedicated_support"
            ],
            "display_order": 4,
            "is_active": True,
            "is_public": False,
            "created_at": now,
            "updated_at": now,
        },
    ])

    # =========================================================================
    # Seed add-on products
    # =========================================================================
    addon_products = sa.table(
        "addon_products",
        sa.column("code", sa.String),
        sa.column("name", sa.String),
        sa.column("description", sa.Text),
        sa.column("category", sa.String),
        sa.column("price_cents", sa.Integer),
        sa.column("billing_period", sa.String),
        sa.column("quantity_unit", sa.String),
        sa.column("quantity_value", sa.Integer),
        sa.column("display_order", sa.Integer),
        sa.column("is_active", sa.Boolean),
        sa.column("created_at", sa.DateTime),
        sa.column("updated_at", sa.DateTime),
    )

    op.bulk_insert(addon_products, [
        {
            "code": "domain",
            "name": "Custom Domain",
            "description": "Connect your own domain with SSL certificate included",
            "category": "domain",
            "price_cents": 1500,
            "billing_period": "annual",
            "quantity_unit": None,
            "quantity_value": None,
            "display_order": 1,
            "is_active": True,
            "created_at": now,
            "updated_at": now,
        },
        {
            "code": "email_5",
            "name": "5 Email Addresses",
            "description": "Professional email addresses on your domain",
            "category": "email",
            "price_cents": 500,
            "billing_period": "monthly",
            "quantity_unit": "emails",
            "quantity_value": 5,
            "display_order": 2,
            "is_active": True,
            "created_at": now,
            "updated_at": now,
        },
        {
            "code": "email_10",
            "name": "10 Email Addresses",
            "description": "Professional email addresses on your domain",
            "category": "email",
            "price_cents": 900,
            "billing_period": "monthly",
            "quantity_unit": "emails",
            "quantity_value": 10,
            "display_order": 3,
            "is_active": True,
            "created_at": now,
            "updated_at": now,
        },
        {
            "code": "email_25",
            "name": "25 Email Addresses",
            "description": "Professional email addresses on your domain",
            "category": "email",
            "price_cents": 1900,
            "billing_period": "monthly",
            "quantity_unit": "emails",
            "quantity_value": 25,
            "display_order": 4,
            "is_active": True,
            "created_at": now,
            "updated_at": now,
        },
        {
            "code": "storage_10gb",
            "name": "Additional Storage (10GB)",
            "description": "Extra storage for product images and files",
            "category": "storage",
            "price_cents": 500,
            "billing_period": "monthly",
            "quantity_unit": "GB",
            "quantity_value": 10,
            "display_order": 5,
            "is_active": True,
            "created_at": now,
            "updated_at": now,
        },
    ])


def downgrade() -> None:
    # Remove new columns from vendor_subscriptions
    op.drop_column("vendor_subscriptions", "last_payment_error")
    op.drop_column("vendor_subscriptions", "payment_retry_count")
    op.drop_column("vendor_subscriptions", "scheduled_change_at")
    op.drop_column("vendor_subscriptions", "scheduled_tier_change")
    op.drop_column("vendor_subscriptions", "proration_behavior")
    op.drop_column("vendor_subscriptions", "stripe_payment_method_id")
    op.drop_column("vendor_subscriptions", "stripe_price_id")

    # Drop stripe_webhook_events
    op.drop_index(op.f("ix_stripe_webhook_events_vendor_id"), table_name="stripe_webhook_events")
    op.drop_index(op.f("ix_stripe_webhook_events_subscription_id"), table_name="stripe_webhook_events")
    op.drop_index(op.f("ix_stripe_webhook_events_status"), table_name="stripe_webhook_events")
    op.drop_index(op.f("ix_stripe_webhook_events_id"), table_name="stripe_webhook_events")
    op.drop_index(op.f("ix_stripe_webhook_events_event_type"), table_name="stripe_webhook_events")
    op.drop_index(op.f("ix_stripe_webhook_events_event_id"), table_name="stripe_webhook_events")
    op.drop_index("idx_webhook_event_type_status", table_name="stripe_webhook_events")
    op.drop_table("stripe_webhook_events")

    # Drop vendor_addons
    op.drop_index(op.f("ix_vendor_addons_vendor_id"), table_name="vendor_addons")
    op.drop_index(op.f("ix_vendor_addons_status"), table_name="vendor_addons")
    op.drop_index(op.f("ix_vendor_addons_id"), table_name="vendor_addons")
    op.drop_index(op.f("ix_vendor_addons_domain_name"), table_name="vendor_addons")
    op.drop_index(op.f("ix_vendor_addons_addon_product_id"), table_name="vendor_addons")
    op.drop_index("idx_vendor_addon_status", table_name="vendor_addons")
    op.drop_index("idx_vendor_addon_product", table_name="vendor_addons")
    op.drop_table("vendor_addons")

    # Drop billing_history
    op.drop_index(op.f("ix_billing_history_vendor_id"), table_name="billing_history")
    op.drop_index(op.f("ix_billing_history_stripe_invoice_id"), table_name="billing_history")
    op.drop_index(op.f("ix_billing_history_status"), table_name="billing_history")
    op.drop_index(op.f("ix_billing_history_id"), table_name="billing_history")
    op.drop_index("idx_billing_vendor_date", table_name="billing_history")
    op.drop_index("idx_billing_status", table_name="billing_history")
    op.drop_table("billing_history")

    # Drop addon_products
    op.drop_index(op.f("ix_addon_products_id"), table_name="addon_products")
    op.drop_index(op.f("ix_addon_products_code"), table_name="addon_products")
    op.drop_index(op.f("ix_addon_products_category"), table_name="addon_products")
    op.drop_table("addon_products")

    # Drop subscription_tiers
    op.drop_index(op.f("ix_subscription_tiers_id"), table_name="subscription_tiers")
    op.drop_index(op.f("ix_subscription_tiers_code"), table_name="subscription_tiers")
    op.drop_table("subscription_tiers")
