"""Add OrderItem

Revision ID: 78b2c37d5aa0
Revises: 9be29fe8ca0f
Create Date: 2025-03-11 14:27:16.542483

"""

import concurrent.futures
import datetime
import itertools
import random
import time
from typing import Any, TypedDict, cast
from uuid import UUID

import sqlalchemy as sa
import sqlalchemy.exc
import stripe as stripe_lib
from alembic import op

# Polar Custom Imports

# revision identifiers, used by Alembic.
revision = "78b2c37d5aa0"
down_revision = "9be29fe8ca0f"
branch_labels: tuple[str] | None = None
depends_on: tuple[str] | None = None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "order_items",
        sa.Column("label", sa.String(), nullable=False),
        sa.Column("amount", sa.Integer(), nullable=False),
        sa.Column("tax_amount", sa.Integer(), nullable=False),
        sa.Column("proration", sa.Boolean(), nullable=False),
        sa.Column("order_id", sa.Uuid(), nullable=False),
        sa.Column("product_price_id", sa.Uuid(), nullable=True),
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("created_at", sa.TIMESTAMP(timezone=True), nullable=False),
        sa.Column("modified_at", sa.TIMESTAMP(timezone=True), nullable=True),
        sa.Column("deleted_at", sa.TIMESTAMP(timezone=True), nullable=True),
        sa.ForeignKeyConstraint(
            ["order_id"],
            ["orders.id"],
            name=op.f("order_items_order_id_fkey"),
            ondelete="cascade",
        ),
        sa.ForeignKeyConstraint(
            ["product_price_id"],
            ["product_prices.id"],
            name=op.f("order_items_product_price_id_fkey"),
            ondelete="cascade",
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("order_items_pkey")),
    )
    op.create_index(
        op.f("ix_order_items_created_at"), "order_items", ["created_at"], unique=False
    )
    op.create_index(
        op.f("ix_order_items_deleted_at"), "order_items", ["deleted_at"], unique=False
    )
    op.create_index(
        op.f("ix_order_items_modified_at"), "order_items", ["modified_at"], unique=False
    )

    # Ugrade legacy donations without stripe_invoice_id
    op.execute(
        """
        INSERT INTO order_items (
            id,
            created_at,
            label,
            amount,
            tax_amount,
            proration,
            order_id,
            product_price_id
        )
        SELECT
            uuid_generate_v4(),
            orders.created_at,
            'Donation',
            orders.amount,
            orders.tax_amount,
            false,
            orders.id,
            orders.product_price_id
        FROM orders
        WHERE orders.stripe_invoice_id IS NULL
        """
    )

    conn = op.get_bind()
    inspector = sa.inspect(conn)

    foreign_keys = inspector.get_foreign_keys("orders")
    for fk in foreign_keys:
        if fk["name"] in [
            "orders_product_price_id_fkey",
            "sales_product_price_id_fkey",
        ]:
            op.drop_constraint(fk["name"], "orders", type_="foreignkey")

    op.add_column("orders", sa.Column("discount_amount", sa.Integer(), nullable=True))
    op.execute(
        """
        UPDATE orders
        SET discount_amount = 0
        """
    )
    op.alter_column("orders", "discount_amount", nullable=False)
    op.alter_column("orders", "amount", new_column_name="subtotal_amount")
    op.drop_column("orders", "product_price_id")

    op.create_index(
        "ix_net_amount",
        "orders",
        [sa.literal_column("(subtotal_amount - discount_amount)")],
        unique=False,
    )
    op.create_index(
        "ix_total_amount",
        "orders",
        [sa.literal_column("(subtotal_amount - discount_amount + tax_amount)")],
        unique=False,
    )

    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index("ix_total_amount", table_name="orders")
    op.drop_index("ix_subtotal_amount", table_name="orders")

    op.drop_column("orders", "discount_amount")
    op.alter_column("orders", "subtotal_amount", new_column_name="amount")

    op.add_column(
        "orders",
        sa.Column("product_price_id", sa.UUID(), autoincrement=False, nullable=True),
    )
    op.create_foreign_key(
        "orders_product_price_id_fkey",
        "orders",
        "product_prices",
        ["product_price_id"],
        ["id"],
    )

    op.execute(
        """
        UPDATE orders
        SET product_price_id = (
            SELECT product_price_id
            FROM order_items
            WHERE order_items.order_id = orders.id
            LIMIT 1
        )
        """
    )

    op.drop_index(op.f("ix_order_items_modified_at"), table_name="order_items")
    op.drop_index(op.f("ix_order_items_deleted_at"), table_name="order_items")
    op.drop_index(op.f("ix_order_items_created_at"), table_name="order_items")
    op.drop_table("order_items")
    # ### end Alembic commands ###
