"""migrate resource type from enum to string to account for custom taxonomies

Revision ID: 303287c70600
Revises: 3ff6449c099e
Create Date: 2025-10-22 15:31:12.980243

"""

import sqlalchemy as sa
from alembic import op
from loguru import logger

# revision identifiers, used by Alembic.
revision = "303287c70600"
down_revision = "3ff6449c099e"
branch_labels = None
depends_on = None

# Original enum values used by ResourceTypes
RESOURCE_TYPES = (
    "system",
    "data use",
    "data category",
    "data subject",
    "privacy declaration",
)

# Name for the PostgreSQL enum type that backs ResourceTypes
PG_ENUM_NAME = "resourcetypes"

# Mapping from old enum values (with underscores) to new string values (with spaces)
# The old PostgreSQL enum used underscores but the Python ResourceTypes enum expects spaces
RESOURCE_TYPE_MAPPING = {
    "data_use": "data use",
    "data_category": "data category",
    "data_subject": "data subject",
    "privacy_declaration": "privacy declaration",
}


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    # Drop unique functional index that references resource_type
    op.drop_index(
        "ix_plus_custom_field_definition_unique_lowername_resourcetype",
        table_name="plus_custom_field_definition",
    )

    # Alter resource_type columns from Enum -> String
    # Use a PostgreSQL USING clause to safely cast enum -> text
    op.alter_column(
        "plus_custom_field_definition",
        "resource_type",
        existing_type=sa.Enum(*RESOURCE_TYPES, name=PG_ENUM_NAME),
        type_=sa.String(),
        postgresql_using="resource_type::text",
        nullable=False,
    )
    op.alter_column(
        "plus_custom_field",
        "resource_type",
        existing_type=sa.Enum(*RESOURCE_TYPES, name=PG_ENUM_NAME),
        type_=sa.String(),
        postgresql_using="resource_type::text",
        nullable=False,
    )

    # Data migration: Convert old enum values (with underscores) to new string values (with spaces)
    # The old PostgreSQL enum used underscores (e.g., 'privacy_declaration', 'data_use') but the Python
    # ResourceTypes enum expects spaces (e.g., 'privacy declaration', 'data use')
    for old_value, new_value in RESOURCE_TYPE_MAPPING.items():
        for table_name in ["plus_custom_field_definition", "plus_custom_field"]:
            op.execute(
                f"""
                UPDATE {table_name}
                SET resource_type = '{new_value}'
                WHERE resource_type = '{old_value}'
                """
            )

    # Recreate unique functional index on (resource_type, lower(name))
    # Note: Use a raw expression for lower(name)
    op.create_index(
        "ix_plus_custom_field_definition_unique_lowername_resourcetype",
        "plus_custom_field_definition",
        ["resource_type", sa.text("lower(name)")],
        unique=True,
    )

    # Drop the unused enum type after all columns have been converted
    op.execute(f'DROP TYPE IF EXISTS "{PG_ENUM_NAME}"')
    # ### end Alembic commands ###


def downgrade():
    """
    This migration does not support downgrades.
    """
    logger.info("Conversion of str to enum ResourceType is unsupported.")
