"""unified_order_schema

Revision ID: c1d2e3f4a5b6
Revises: 2362c2723a93
Create Date: 2025-12-19

This migration implements the unified order schema:
- Removes the separate letzshop_orders table
- Enhances the orders table with:
  - Customer/address snapshots (preserved at order time)
  - External marketplace references
  - Tracking provider field
- Enhances order_items with:
  - GTIN fields
  - External item references
  - Item state for marketplace confirmation flow
- Updates letzshop_fulfillment_queue to reference orders table directly

Design principles:
- Single orders table for all channels (direct, letzshop, etc.)
- Customer/address data snapshotted at order time
- Products must exist in catalog (enforced by FK)
"""
from collections.abc import Sequence

import sqlalchemy as sa
from sqlalchemy import inspect

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "c1d2e3f4a5b6"
down_revision: str | None = "2362c2723a93"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def table_exists(table_name: str) -> bool:
    """Check if a table exists in the database."""
    bind = op.get_bind()
    inspector = inspect(bind)
    return table_name in inspector.get_table_names()


def index_exists(index_name: str, table_name: str) -> bool:
    """Check if an index exists on a table."""
    bind = op.get_bind()
    inspector = inspect(bind)
    try:
        indexes = inspector.get_indexes(table_name)
        return any(idx["name"] == index_name for idx in indexes)
    except Exception:
        return False


def safe_drop_index(index_name: str, table_name: str) -> None:
    """Drop an index if it exists."""
    if index_exists(index_name, table_name):
        op.drop_index(index_name, table_name=table_name)


def safe_drop_table(table_name: str) -> None:
    """Drop a table if it exists."""
    if table_exists(table_name):
        op.drop_table(table_name)


def upgrade() -> None:
    # =========================================================================
    # Step 1: Drop old tables that will be replaced (if they exist)
    # =========================================================================

    # Drop letzshop_fulfillment_queue (references letzshop_orders)
    if table_exists("letzshop_fulfillment_queue"):
        safe_drop_index("idx_fulfillment_queue_retry", "letzshop_fulfillment_queue")
        safe_drop_index("idx_fulfillment_queue_status", "letzshop_fulfillment_queue")
        safe_drop_index("ix_letzshop_fulfillment_queue_vendor_id", "letzshop_fulfillment_queue")
        safe_drop_index("ix_letzshop_fulfillment_queue_id", "letzshop_fulfillment_queue")
        op.drop_table("letzshop_fulfillment_queue")

    # Drop letzshop_orders table (replaced by unified orders)
    if table_exists("letzshop_orders"):
        safe_drop_index("idx_letzshop_order_sync", "letzshop_orders")
        safe_drop_index("idx_letzshop_order_state", "letzshop_orders")
        safe_drop_index("idx_letzshop_order_vendor", "letzshop_orders")
        safe_drop_index("ix_letzshop_orders_vendor_id", "letzshop_orders")
        safe_drop_index("ix_letzshop_orders_letzshop_shipment_id", "letzshop_orders")
        safe_drop_index("ix_letzshop_orders_letzshop_order_id", "letzshop_orders")
        safe_drop_index("ix_letzshop_orders_id", "letzshop_orders")
        op.drop_table("letzshop_orders")

    # Drop order_items (references orders)
    if table_exists("order_items"):
        safe_drop_index("ix_order_items_id", "order_items")
        safe_drop_index("ix_order_items_order_id", "order_items")
        op.drop_table("order_items")

    # Drop old orders table
    if table_exists("orders"):
        safe_drop_index("ix_orders_external_order_id", "orders")
        safe_drop_index("ix_orders_channel", "orders")
        safe_drop_index("ix_orders_vendor_id", "orders")
        safe_drop_index("ix_orders_status", "orders")
        safe_drop_index("ix_orders_order_number", "orders")
        safe_drop_index("ix_orders_id", "orders")
        safe_drop_index("ix_orders_customer_id", "orders")
        op.drop_table("orders")

    # =========================================================================
    # Step 2: Create new unified orders table
    # =========================================================================
    op.create_table("orders",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("vendor_id", sa.Integer(), nullable=False),
        sa.Column("customer_id", sa.Integer(), nullable=False),
        sa.Column("order_number", sa.String(length=100), nullable=False),

        # Channel/Source
        sa.Column("channel", sa.String(length=50), nullable=False, server_default="direct"),

        # External references (for marketplace orders)
        sa.Column("external_order_id", sa.String(length=100), nullable=True),
        sa.Column("external_shipment_id", sa.String(length=100), nullable=True),
        sa.Column("external_order_number", sa.String(length=100), nullable=True),
        sa.Column("external_data", sa.JSON(), nullable=True),

        # Status
        sa.Column("status", sa.String(length=50), nullable=False, server_default="pending"),

        # Financials
        sa.Column("subtotal", sa.Float(), nullable=True),
        sa.Column("tax_amount", sa.Float(), nullable=True),
        sa.Column("shipping_amount", sa.Float(), nullable=True),
        sa.Column("discount_amount", sa.Float(), nullable=True),
        sa.Column("total_amount", sa.Float(), nullable=False),
        sa.Column("currency", sa.String(length=10), server_default="EUR", nullable=True),

        # Customer snapshot
        sa.Column("customer_first_name", sa.String(length=100), nullable=False),
        sa.Column("customer_last_name", sa.String(length=100), nullable=False),
        sa.Column("customer_email", sa.String(length=255), nullable=False),
        sa.Column("customer_phone", sa.String(length=50), nullable=True),
        sa.Column("customer_locale", sa.String(length=10), nullable=True),

        # Shipping address snapshot
        sa.Column("ship_first_name", sa.String(length=100), nullable=False),
        sa.Column("ship_last_name", sa.String(length=100), nullable=False),
        sa.Column("ship_company", sa.String(length=200), nullable=True),
        sa.Column("ship_address_line_1", sa.String(length=255), nullable=False),
        sa.Column("ship_address_line_2", sa.String(length=255), nullable=True),
        sa.Column("ship_city", sa.String(length=100), nullable=False),
        sa.Column("ship_postal_code", sa.String(length=20), nullable=False),
        sa.Column("ship_country_iso", sa.String(length=5), nullable=False),

        # Billing address snapshot
        sa.Column("bill_first_name", sa.String(length=100), nullable=False),
        sa.Column("bill_last_name", sa.String(length=100), nullable=False),
        sa.Column("bill_company", sa.String(length=200), nullable=True),
        sa.Column("bill_address_line_1", sa.String(length=255), nullable=False),
        sa.Column("bill_address_line_2", sa.String(length=255), nullable=True),
        sa.Column("bill_city", sa.String(length=100), nullable=False),
        sa.Column("bill_postal_code", sa.String(length=20), nullable=False),
        sa.Column("bill_country_iso", sa.String(length=5), nullable=False),

        # Tracking
        sa.Column("shipping_method", sa.String(length=100), nullable=True),
        sa.Column("tracking_number", sa.String(length=100), nullable=True),
        sa.Column("tracking_provider", sa.String(length=100), nullable=True),

        # Notes
        sa.Column("customer_notes", sa.Text(), nullable=True),
        sa.Column("internal_notes", sa.Text(), nullable=True),

        # Timestamps
        sa.Column("order_date", sa.DateTime(timezone=True), nullable=False),
        sa.Column("confirmed_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("shipped_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("delivered_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("cancelled_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),

        # Foreign keys
        sa.ForeignKeyConstraint(["customer_id"], ["customers.id"]),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"]),
        sa.PrimaryKeyConstraint("id")
    )

    # Indexes for orders
    op.create_index(op.f("ix_orders_id"), "orders", ["id"], unique=False)
    op.create_index(op.f("ix_orders_vendor_id"), "orders", ["vendor_id"], unique=False)
    op.create_index(op.f("ix_orders_customer_id"), "orders", ["customer_id"], unique=False)
    op.create_index(op.f("ix_orders_order_number"), "orders", ["order_number"], unique=True)
    op.create_index(op.f("ix_orders_channel"), "orders", ["channel"], unique=False)
    op.create_index(op.f("ix_orders_status"), "orders", ["status"], unique=False)
    op.create_index(op.f("ix_orders_external_order_id"), "orders", ["external_order_id"], unique=False)
    op.create_index(op.f("ix_orders_external_shipment_id"), "orders", ["external_shipment_id"], unique=False)
    op.create_index("idx_order_vendor_status", "orders", ["vendor_id", "status"], unique=False)
    op.create_index("idx_order_vendor_channel", "orders", ["vendor_id", "channel"], unique=False)
    op.create_index("idx_order_vendor_date", "orders", ["vendor_id", "order_date"], unique=False)

    # =========================================================================
    # Step 3: Create new order_items table
    # =========================================================================
    op.create_table("order_items",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("order_id", sa.Integer(), nullable=False),
        sa.Column("product_id", sa.Integer(), nullable=False),

        # Product snapshot
        sa.Column("product_name", sa.String(length=255), nullable=False),
        sa.Column("product_sku", sa.String(length=100), nullable=True),
        sa.Column("gtin", sa.String(length=50), nullable=True),
        sa.Column("gtin_type", sa.String(length=20), nullable=True),

        # Pricing
        sa.Column("quantity", sa.Integer(), nullable=False),
        sa.Column("unit_price", sa.Float(), nullable=False),
        sa.Column("total_price", sa.Float(), nullable=False),

        # External references (for marketplace items)
        sa.Column("external_item_id", sa.String(length=100), nullable=True),
        sa.Column("external_variant_id", sa.String(length=100), nullable=True),

        # Item state (for marketplace confirmation flow)
        sa.Column("item_state", sa.String(length=50), nullable=True),

        # Inventory tracking
        sa.Column("inventory_reserved", sa.Boolean(), server_default="0", nullable=True),
        sa.Column("inventory_fulfilled", sa.Boolean(), server_default="0", nullable=True),

        # Timestamps
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),

        # Foreign keys
        sa.ForeignKeyConstraint(["order_id"], ["orders.id"]),
        sa.ForeignKeyConstraint(["product_id"], ["products.id"]),
        sa.PrimaryKeyConstraint("id")
    )

    # Indexes for order_items
    op.create_index(op.f("ix_order_items_id"), "order_items", ["id"], unique=False)
    op.create_index(op.f("ix_order_items_order_id"), "order_items", ["order_id"], unique=False)
    op.create_index(op.f("ix_order_items_product_id"), "order_items", ["product_id"], unique=False)
    op.create_index(op.f("ix_order_items_gtin"), "order_items", ["gtin"], unique=False)

    # =========================================================================
    # Step 4: Create updated letzshop_fulfillment_queue (references orders)
    # =========================================================================
    op.create_table("letzshop_fulfillment_queue",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("vendor_id", sa.Integer(), nullable=False),
        sa.Column("order_id", sa.Integer(), nullable=False),

        # Operation type
        sa.Column("operation", sa.String(length=50), nullable=False),

        # Operation payload
        sa.Column("payload", sa.JSON(), nullable=False),

        # Status and retry
        sa.Column("status", sa.String(length=50), server_default="pending", nullable=True),
        sa.Column("attempts", sa.Integer(), server_default="0", nullable=True),
        sa.Column("max_attempts", sa.Integer(), server_default="3", nullable=True),
        sa.Column("last_attempt_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("next_retry_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("error_message", sa.Text(), nullable=True),
        sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True),

        # Response from Letzshop
        sa.Column("response_data", sa.JSON(), nullable=True),

        # Timestamps
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),

        # Foreign keys
        sa.ForeignKeyConstraint(["order_id"], ["orders.id"]),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"]),
        sa.PrimaryKeyConstraint("id")
    )

    # Indexes for letzshop_fulfillment_queue
    op.create_index(op.f("ix_letzshop_fulfillment_queue_id"), "letzshop_fulfillment_queue", ["id"], unique=False)
    op.create_index(op.f("ix_letzshop_fulfillment_queue_vendor_id"), "letzshop_fulfillment_queue", ["vendor_id"], unique=False)
    op.create_index(op.f("ix_letzshop_fulfillment_queue_order_id"), "letzshop_fulfillment_queue", ["order_id"], unique=False)
    op.create_index("idx_fulfillment_queue_status", "letzshop_fulfillment_queue", ["status", "vendor_id"], unique=False)
    op.create_index("idx_fulfillment_queue_retry", "letzshop_fulfillment_queue", ["status", "next_retry_at"], unique=False)
    op.create_index("idx_fulfillment_queue_order", "letzshop_fulfillment_queue", ["order_id"], unique=False)


def downgrade() -> None:
    # Drop new letzshop_fulfillment_queue
    safe_drop_index("idx_fulfillment_queue_order", "letzshop_fulfillment_queue")
    safe_drop_index("idx_fulfillment_queue_retry", "letzshop_fulfillment_queue")
    safe_drop_index("idx_fulfillment_queue_status", "letzshop_fulfillment_queue")
    safe_drop_index("ix_letzshop_fulfillment_queue_order_id", "letzshop_fulfillment_queue")
    safe_drop_index("ix_letzshop_fulfillment_queue_vendor_id", "letzshop_fulfillment_queue")
    safe_drop_index("ix_letzshop_fulfillment_queue_id", "letzshop_fulfillment_queue")
    safe_drop_table("letzshop_fulfillment_queue")

    # Drop new order_items
    safe_drop_index("ix_order_items_gtin", "order_items")
    safe_drop_index("ix_order_items_product_id", "order_items")
    safe_drop_index("ix_order_items_order_id", "order_items")
    safe_drop_index("ix_order_items_id", "order_items")
    safe_drop_table("order_items")

    # Drop new orders
    safe_drop_index("idx_order_vendor_date", "orders")
    safe_drop_index("idx_order_vendor_channel", "orders")
    safe_drop_index("idx_order_vendor_status", "orders")
    safe_drop_index("ix_orders_external_shipment_id", "orders")
    safe_drop_index("ix_orders_external_order_id", "orders")
    safe_drop_index("ix_orders_status", "orders")
    safe_drop_index("ix_orders_channel", "orders")
    safe_drop_index("ix_orders_order_number", "orders")
    safe_drop_index("ix_orders_customer_id", "orders")
    safe_drop_index("ix_orders_vendor_id", "orders")
    safe_drop_index("ix_orders_id", "orders")
    safe_drop_table("orders")

    # Recreate old orders table
    op.create_table("orders",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("vendor_id", sa.Integer(), nullable=False),
        sa.Column("customer_id", sa.Integer(), nullable=False),
        sa.Column("order_number", sa.String(), nullable=False),
        sa.Column("channel", sa.String(length=50), nullable=True, server_default="direct"),
        sa.Column("external_order_id", sa.String(length=100), nullable=True),
        sa.Column("external_channel_data", sa.JSON(), nullable=True),
        sa.Column("status", sa.String(), nullable=False),
        sa.Column("subtotal", sa.Float(), nullable=False),
        sa.Column("tax_amount", sa.Float(), nullable=True),
        sa.Column("shipping_amount", sa.Float(), nullable=True),
        sa.Column("discount_amount", sa.Float(), nullable=True),
        sa.Column("total_amount", sa.Float(), nullable=False),
        sa.Column("currency", sa.String(), nullable=True),
        sa.Column("shipping_address_id", sa.Integer(), nullable=False),
        sa.Column("billing_address_id", sa.Integer(), nullable=False),
        sa.Column("shipping_method", sa.String(), nullable=True),
        sa.Column("tracking_number", sa.String(), nullable=True),
        sa.Column("customer_notes", sa.Text(), nullable=True),
        sa.Column("internal_notes", sa.Text(), nullable=True),
        sa.Column("paid_at", sa.DateTime(), nullable=True),
        sa.Column("shipped_at", sa.DateTime(), nullable=True),
        sa.Column("delivered_at", sa.DateTime(), nullable=True),
        sa.Column("cancelled_at", sa.DateTime(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["billing_address_id"], ["customer_addresses.id"]),
        sa.ForeignKeyConstraint(["customer_id"], ["customers.id"]),
        sa.ForeignKeyConstraint(["shipping_address_id"], ["customer_addresses.id"]),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"]),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index(op.f("ix_orders_customer_id"), "orders", ["customer_id"], unique=False)
    op.create_index(op.f("ix_orders_id"), "orders", ["id"], unique=False)
    op.create_index(op.f("ix_orders_order_number"), "orders", ["order_number"], unique=True)
    op.create_index(op.f("ix_orders_status"), "orders", ["status"], unique=False)
    op.create_index(op.f("ix_orders_vendor_id"), "orders", ["vendor_id"], unique=False)
    op.create_index(op.f("ix_orders_channel"), "orders", ["channel"], unique=False)
    op.create_index(op.f("ix_orders_external_order_id"), "orders", ["external_order_id"], unique=False)

    # Recreate old order_items table
    op.create_table("order_items",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("order_id", sa.Integer(), nullable=False),
        sa.Column("product_id", sa.Integer(), nullable=False),
        sa.Column("product_name", sa.String(), nullable=False),
        sa.Column("product_sku", sa.String(), nullable=True),
        sa.Column("quantity", sa.Integer(), nullable=False),
        sa.Column("unit_price", sa.Float(), nullable=False),
        sa.Column("total_price", sa.Float(), nullable=False),
        sa.Column("inventory_reserved", sa.Boolean(), nullable=True),
        sa.Column("inventory_fulfilled", sa.Boolean(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["order_id"], ["orders.id"]),
        sa.ForeignKeyConstraint(["product_id"], ["products.id"]),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index(op.f("ix_order_items_id"), "order_items", ["id"], unique=False)
    op.create_index(op.f("ix_order_items_order_id"), "order_items", ["order_id"], unique=False)

    # Recreate old letzshop_orders table
    op.create_table("letzshop_orders",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("vendor_id", sa.Integer(), nullable=False),
        sa.Column("letzshop_order_id", sa.String(length=100), nullable=False),
        sa.Column("letzshop_shipment_id", sa.String(length=100), nullable=True),
        sa.Column("letzshop_order_number", sa.String(length=100), nullable=True),
        sa.Column("local_order_id", sa.Integer(), nullable=True),
        sa.Column("letzshop_state", sa.String(length=50), nullable=True),
        sa.Column("customer_email", sa.String(length=255), nullable=True),
        sa.Column("customer_name", sa.String(length=255), nullable=True),
        sa.Column("total_amount", sa.String(length=50), nullable=True),
        sa.Column("currency", sa.String(length=10), server_default="EUR", nullable=True),
        sa.Column("customer_locale", sa.String(length=10), nullable=True),
        sa.Column("shipping_country_iso", sa.String(length=5), nullable=True),
        sa.Column("billing_country_iso", sa.String(length=5), nullable=True),
        sa.Column("order_date", sa.DateTime(timezone=True), nullable=True),
        sa.Column("raw_order_data", sa.JSON(), nullable=True),
        sa.Column("inventory_units", sa.JSON(), nullable=True),
        sa.Column("sync_status", sa.String(length=50), server_default="pending", nullable=True),
        sa.Column("last_synced_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("sync_error", sa.Text(), nullable=True),
        sa.Column("confirmed_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("rejected_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("tracking_set_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("tracking_number", sa.String(length=100), nullable=True),
        sa.Column("tracking_carrier", sa.String(length=100), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),
        sa.ForeignKeyConstraint(["local_order_id"], ["orders.id"]),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"]),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index(op.f("ix_letzshop_orders_id"), "letzshop_orders", ["id"], unique=False)
    op.create_index(op.f("ix_letzshop_orders_letzshop_order_id"), "letzshop_orders", ["letzshop_order_id"], unique=False)
    op.create_index(op.f("ix_letzshop_orders_letzshop_shipment_id"), "letzshop_orders", ["letzshop_shipment_id"], unique=False)
    op.create_index(op.f("ix_letzshop_orders_vendor_id"), "letzshop_orders", ["vendor_id"], unique=False)
    op.create_index("idx_letzshop_order_vendor", "letzshop_orders", ["vendor_id", "letzshop_order_id"], unique=False)
    op.create_index("idx_letzshop_order_state", "letzshop_orders", ["vendor_id", "letzshop_state"], unique=False)
    op.create_index("idx_letzshop_order_sync", "letzshop_orders", ["vendor_id", "sync_status"], unique=False)

    # Recreate old letzshop_fulfillment_queue table
    op.create_table("letzshop_fulfillment_queue",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("vendor_id", sa.Integer(), nullable=False),
        sa.Column("letzshop_order_id", sa.Integer(), nullable=False),
        sa.Column("operation", sa.String(length=50), nullable=False),
        sa.Column("payload", sa.JSON(), nullable=False),
        sa.Column("status", sa.String(length=50), server_default="pending", nullable=True),
        sa.Column("attempts", sa.Integer(), server_default="0", nullable=True),
        sa.Column("max_attempts", sa.Integer(), server_default="3", nullable=True),
        sa.Column("last_attempt_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("next_retry_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("error_message", sa.Text(), nullable=True),
        sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("response_data", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("(CURRENT_TIMESTAMP)"), nullable=False),
        sa.ForeignKeyConstraint(["letzshop_order_id"], ["letzshop_orders.id"]),
        sa.ForeignKeyConstraint(["vendor_id"], ["vendors.id"]),
        sa.PrimaryKeyConstraint("id")
    )
    op.create_index(op.f("ix_letzshop_fulfillment_queue_id"), "letzshop_fulfillment_queue", ["id"], unique=False)
    op.create_index(op.f("ix_letzshop_fulfillment_queue_vendor_id"), "letzshop_fulfillment_queue", ["vendor_id"], unique=False)
    op.create_index("idx_fulfillment_queue_status", "letzshop_fulfillment_queue", ["status", "vendor_id"], unique=False)
    op.create_index("idx_fulfillment_queue_retry", "letzshop_fulfillment_queue", ["status", "next_retry_at"], unique=False)
