"""Add country_iso to customer_addresses

Revision ID: r6f7a8b9c0d1
Revises: q5e6f7a8b9c0
Create Date: 2026-01-02

Adds country_iso field to customer_addresses table and renames
country to country_name for clarity.

This migration is idempotent - it checks for existing columns before
making changes.
"""

import sqlalchemy as sa
from sqlalchemy import text

from alembic import op

# revision identifiers, used by Alembic.
revision = "r6f7a8b9c0d1"
down_revision = "q5e6f7a8b9c0"
branch_labels = None
depends_on = None


# Country name to ISO code mapping for backfill
COUNTRY_ISO_MAP = {
    "Luxembourg": "LU",
    "Germany": "DE",
    "France": "FR",
    "Belgium": "BE",
    "Netherlands": "NL",
    "Austria": "AT",
    "Italy": "IT",
    "Spain": "ES",
    "Portugal": "PT",
    "Poland": "PL",
    "Czech Republic": "CZ",
    "Czechia": "CZ",
    "Slovakia": "SK",
    "Hungary": "HU",
    "Romania": "RO",
    "Bulgaria": "BG",
    "Greece": "GR",
    "Croatia": "HR",
    "Slovenia": "SI",
    "Estonia": "EE",
    "Latvia": "LV",
    "Lithuania": "LT",
    "Finland": "FI",
    "Sweden": "SE",
    "Denmark": "DK",
    "Ireland": "IE",
    "Cyprus": "CY",
    "Malta": "MT",
    "United Kingdom": "GB",
    "Switzerland": "CH",
    "United States": "US",
}


def get_column_names(connection, table_name):
    """Get list of column names for a table (PostgreSQL)."""
    result = connection.execute(text(
        "SELECT column_name FROM information_schema.columns "
        "WHERE table_name = :table AND table_schema = 'public'"
    ), {"table": table_name})
    return [row[0] for row in result]


def upgrade() -> None:
    connection = op.get_bind()
    columns = get_column_names(connection, "customer_addresses")

    # Check if we need to do anything (idempotent check)
    has_country = "country" in columns
    has_country_name = "country_name" in columns
    has_country_iso = "country_iso" in columns

    # If already has new columns, nothing to do
    if has_country_name and has_country_iso:
        print("  Columns country_name and country_iso already exist, skipping")
        return

    # If has old 'country' column, rename it (PostgreSQL supports direct rename)
    if has_country and not has_country_name:
        op.alter_column(
            "customer_addresses",
            "country",
            new_column_name="country_name",
        )

    # Add country_iso if it doesn't exist
    if not has_country_iso:
        op.add_column(
            "customer_addresses",
            sa.Column("country_iso", sa.String(5), nullable=True)
        )

        # Backfill country_iso from country_name
        for country_name, iso_code in COUNTRY_ISO_MAP.items():
            connection.execute(
                text(
                    "UPDATE customer_addresses SET country_iso = :iso "
                    "WHERE country_name = :name"
                ),
                {"iso": iso_code, "name": country_name},
            )

        # Set default for any remaining NULL values
        connection.execute(
            text(
                "UPDATE customer_addresses SET country_iso = 'LU' "
                "WHERE country_iso IS NULL"
            )
        )

        # Make country_iso NOT NULL (PostgreSQL supports direct alter)
        op.alter_column(
            "customer_addresses",
            "country_iso",
            existing_type=sa.String(5),
            nullable=False,
        )


def downgrade() -> None:
    connection = op.get_bind()
    columns = get_column_names(connection, "customer_addresses")

    has_country_name = "country_name" in columns
    has_country_iso = "country_iso" in columns
    has_country = "country" in columns

    # Only downgrade if in the new state
    if has_country_name and not has_country:
        op.alter_column(
            "customer_addresses",
            "country_name",
            new_column_name="country",
        )

    if has_country_iso:
        op.drop_column("customer_addresses", "country_iso")
