from __future__ import annotations

from alembic import op
import sqlalchemy as sa

revision = "0001_initial_schema"
down_revision = None
branch_labels = None
depends_on = None


def upgrade() -> None:
    op.create_table(
        "customers",
        sa.Column("id", sa.Uuid(), primary_key=True, nullable=False),
        sa.Column("external_customer_reference", sa.String(length=200), nullable=True),
        sa.Column("email", sa.String(length=320), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
    )
    op.create_index("ix_customers_external_customer_reference", "customers", ["external_customer_reference"])
    op.create_index("ix_customers_email", "customers", ["email"])

    op.create_table(
        "licences",
        sa.Column("id", sa.Uuid(), primary_key=True, nullable=False),
        sa.Column("public_licence_identifier", sa.String(length=32), nullable=False),
        sa.Column("licence_key_suffix", sa.String(length=12), nullable=False),
        sa.Column("licence_key_hash", sa.Text(), nullable=False),
        sa.Column("licence_key_hash_version", sa.Integer(), nullable=False),
        sa.Column("licence_type", sa.Enum("PERPETUAL", "SUBSCRIPTION", name="licencetype"), nullable=False),
        sa.Column("status", sa.Enum("ACTIVE", "SUSPENDED", "REVOKED", "EXPIRED", name="licencestatus"), nullable=False),
        sa.Column("customer_id", sa.Uuid(), sa.ForeignKey("customers.id"), nullable=True),
        sa.Column("activation_limit", sa.Integer(), nullable=False),
        sa.Column("subscription_expiry", sa.DateTime(timezone=True), nullable=True),
        sa.Column("update_entitlement_expiry", sa.DateTime(timezone=True), nullable=True),
        sa.Column("support_entitlement_expiry", sa.DateTime(timezone=True), nullable=True),
        sa.Column("metadata_json", sa.JSON(), nullable=False),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
    )
    op.create_index("ix_licences_public_licence_identifier", "licences", ["public_licence_identifier"], unique=True)
    op.create_index("ix_licences_licence_key_suffix", "licences", ["licence_key_suffix"])

    op.create_table(
        "activations",
        sa.Column("id", sa.Uuid(), primary_key=True, nullable=False),
        sa.Column("licence_id", sa.Uuid(), sa.ForeignKey("licences.id"), nullable=False),
        sa.Column("installation_id", sa.String(length=128), nullable=False),
        sa.Column("activation_token_identifier", sa.String(length=32), nullable=False),
        sa.Column("activation_token_suffix", sa.String(length=12), nullable=False),
        sa.Column("activation_token_hash", sa.Text(), nullable=False),
        sa.Column("activation_token_hash_version", sa.Integer(), nullable=False),
        sa.Column("status", sa.Enum("ACTIVE", "DEACTIVATED", "REVOKED", name="activationstatus"), nullable=False),
        sa.Column("activated_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("last_validated_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("deactivated_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
        sa.UniqueConstraint("licence_id", "installation_id", name="uq_activation_licence_installation"),
    )
    op.create_index("ix_activations_installation_id", "activations", ["installation_id"])
    op.create_index("ix_activations_activation_token_identifier", "activations", ["activation_token_identifier"], unique=True)
    op.create_index("ix_activations_status", "activations", ["status"])
    op.create_index("ix_activation_licence_status", "activations", ["licence_id", "status"])

    op.create_table(
        "licence_events",
        sa.Column("id", sa.Uuid(), primary_key=True, nullable=False),
        sa.Column("licence_id", sa.Uuid(), sa.ForeignKey("licences.id"), nullable=True),
        sa.Column("activation_id", sa.Uuid(), sa.ForeignKey("activations.id"), nullable=True),
        sa.Column("event_type", sa.Enum(
            "LICENCE_CREATED",
            "ACTIVATION_SUCCEEDED",
            "ACTIVATION_DENIED",
            "VALIDATION_SUCCEEDED",
            "VALIDATION_DENIED",
            "DEACTIVATION",
            "REVOCATION",
            "SUSPENSION",
            "STATUS_CHANGE",
            name="licenceeventtype",
        ), nullable=False),
        sa.Column("result", sa.String(length=80), nullable=False),
        sa.Column("public_licence_identifier", sa.String(length=32), nullable=True),
        sa.Column("request_correlation_id", sa.String(length=80), nullable=True),
        sa.Column("detail", sa.JSON(), nullable=False),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
    )
    op.create_index("ix_licence_events_public_licence_identifier", "licence_events", ["public_licence_identifier"])
    op.create_index("ix_licence_events_licence_created", "licence_events", ["licence_id", "created_at"])


def downgrade() -> None:
    op.drop_table("licence_events")
    op.drop_table("activations")
    op.drop_table("licences")
    op.drop_table("customers")
    op.execute("DROP TYPE IF EXISTS licenceeventtype")
    op.execute("DROP TYPE IF EXISTS activationstatus")
    op.execute("DROP TYPE IF EXISTS licencestatus")
    op.execute("DROP TYPE IF EXISTS licencetype")
