"""Initial domain schema"""

from __future__ import annotations

from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = "20251109_01"
down_revision = None
branch_labels = None
depends_on = None


mining_operation_type = sa.Enum(
    "open_pit",
    "underground",
    "in_situ_leach",
    "placer",
    "quarry",
    "mountaintop_removal",
    "other",
    name="miningoperationtype",
)

scenario_status = sa.Enum(
    "draft",
    "active",
    "archived",
    name="scenariostatus",
)

financial_category = sa.Enum(
    "capex",
    "opex",
    "revenue",
    "contingency",
    "other",
    name="financialcategory",
)

cost_bucket = sa.Enum(
    "capital_initial",
    "capital_sustaining",
    "operating_fixed",
    "operating_variable",
    "maintenance",
    "reclamation",
    "royalties",
    "general_admin",
    name="costbucket",
)

distribution_type = sa.Enum(
    "normal",
    "triangular",
    "uniform",
    "lognormal",
    "custom",
    name="distributiontype",
)

stochastic_variable = sa.Enum(
    "ore_grade",
    "recovery_rate",
    "metal_price",
    "operating_cost",
    "capital_cost",
    "discount_rate",
    "throughput",
    name="stochasticvariable",
)

resource_type = sa.Enum(
    "diesel",
    "electricity",
    "water",
    "explosives",
    "reagents",
    "labor",
    "equipment_hours",
    "tailings_capacity",
    name="resourcetype",
)


def upgrade() -> None:
    bind = op.get_bind()
    mining_operation_type.create(bind, checkfirst=True)
    scenario_status.create(bind, checkfirst=True)
    financial_category.create(bind, checkfirst=True)
    cost_bucket.create(bind, checkfirst=True)
    distribution_type.create(bind, checkfirst=True)
    stochastic_variable.create(bind, checkfirst=True)
    resource_type.create(bind, checkfirst=True)

    op.create_table(
        "projects",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("location", sa.String(length=255), nullable=True),
        sa.Column("operation_type", mining_operation_type, nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("name"),
    )
    op.create_index(op.f("ix_projects_id"), "projects", ["id"], unique=False)

    op.create_table(
        "scenarios",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("project_id", sa.Integer(), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("status", scenario_status, nullable=False),
        sa.Column("start_date", sa.Date(), nullable=True),
        sa.Column("end_date", sa.Date(), nullable=True),
        sa.Column("discount_rate", sa.Numeric(
            precision=5, scale=2), nullable=True),
        sa.Column("currency", sa.String(length=3), nullable=True),
        sa.Column("primary_resource", resource_type, nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.ForeignKeyConstraint(
            ["project_id"], ["projects.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_scenarios_id"), "scenarios", ["id"], unique=False)
    op.create_index(op.f("ix_scenarios_project_id"),
                    "scenarios", ["project_id"], unique=False)

    op.create_table(
        "financial_inputs",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("scenario_id", sa.Integer(), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("category", financial_category, nullable=False),
        sa.Column("cost_bucket", cost_bucket, nullable=True),
        sa.Column("amount", sa.Numeric(precision=18, scale=2), nullable=False),
        sa.Column("currency", sa.String(length=3), nullable=True),
        sa.Column("effective_date", sa.Date(), nullable=True),
        sa.Column("notes", sa.Text(), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.ForeignKeyConstraint(
            ["scenario_id"], ["scenarios.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_financial_inputs_id"),
                    "financial_inputs", ["id"], unique=False)
    op.create_index(op.f("ix_financial_inputs_scenario_id"),
                    "financial_inputs", ["scenario_id"], unique=False)

    op.create_table(
        "simulation_parameters",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("scenario_id", sa.Integer(), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("distribution", distribution_type, nullable=False),
        sa.Column("variable", stochastic_variable, nullable=True),
        sa.Column("resource_type", resource_type, nullable=True),
        sa.Column("mean_value", sa.Numeric(
            precision=18, scale=4), nullable=True),
        sa.Column("standard_deviation", sa.Numeric(
            precision=18, scale=4), nullable=True),
        sa.Column("minimum_value", sa.Numeric(
            precision=18, scale=4), nullable=True),
        sa.Column("maximum_value", sa.Numeric(
            precision=18, scale=4), nullable=True),
        sa.Column("unit", sa.String(length=32), nullable=True),
        sa.Column("configuration", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True),
                  server_default=sa.func.now(), nullable=False),
        sa.ForeignKeyConstraint(
            ["scenario_id"], ["scenarios.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_simulation_parameters_id"),
                    "simulation_parameters", ["id"], unique=False)
    op.create_index(op.f("ix_simulation_parameters_scenario_id"),
                    "simulation_parameters", ["scenario_id"], unique=False)


def downgrade() -> None:
    op.drop_index(op.f("ix_simulation_parameters_scenario_id"),
                  table_name="simulation_parameters")
    op.drop_index(op.f("ix_simulation_parameters_id"),
                  table_name="simulation_parameters")
    op.drop_table("simulation_parameters")

    op.drop_index(op.f("ix_financial_inputs_scenario_id"),
                  table_name="financial_inputs")
    op.drop_index(op.f("ix_financial_inputs_id"),
                  table_name="financial_inputs")
    op.drop_table("financial_inputs")

    op.drop_index(op.f("ix_scenarios_project_id"), table_name="scenarios")
    op.drop_index(op.f("ix_scenarios_id"), table_name="scenarios")
    op.drop_table("scenarios")

    op.drop_index(op.f("ix_projects_id"), table_name="projects")
    op.drop_table("projects")

    resource_type.drop(op.get_bind(), checkfirst=True)
    stochastic_variable.drop(op.get_bind(), checkfirst=True)
    distribution_type.drop(op.get_bind(), checkfirst=True)
    cost_bucket.drop(op.get_bind(), checkfirst=True)
    financial_category.drop(op.get_bind(), checkfirst=True)
    scenario_status.drop(op.get_bind(), checkfirst=True)
    mining_operation_type.drop(op.get_bind(), checkfirst=True)
