"""Checkpoint C1: socle compteurs, rattachements et relevés audités."""

from alembic import op
import sqlalchemy as sa


revision = "n9c0d1e2f3g4"
down_revision = "m8b9c0d1e2f3"
branch_labels = None
depends_on = None


def upgrade():
    # Les relevés restent auditables après suppression d'un utilisateur ;
    # seule la référence vers l'auteur devient NULL.
    op.drop_constraint("meter_readings_ibfk_2", "meter_readings", type_="foreignkey")
    op.create_foreign_key(
        "fk_meter_readings_read_by", "meter_readings", "users",
        ["read_by_id"], ["id"], ondelete="SET NULL",
    )
    op.alter_column("meters", "equipment_id", existing_type=sa.Integer(), nullable=True)
    for name, target in (
        ("building_id", "buildings"), ("zone_id", "zones"),
        ("room_id", "rooms"), ("housing_unit_id", "housing_units"),
    ):
        op.add_column("meters", sa.Column(name, sa.Integer(), nullable=True))
        op.create_index(f"ix_meters_{name}", "meters", [name])
        op.create_foreign_key(f"fk_meters_{name}", "meters", target, [name], ["id"])
    op.add_column("meters", sa.Column("parent_id", sa.Integer(), nullable=True))
    op.add_column("meters", sa.Column("replaces_meter_id", sa.Integer(), nullable=True))
    op.add_column("meters", sa.Column("usage", sa.String(255), nullable=True))
    op.add_column("meters", sa.Column("status", sa.String(30), nullable=False, server_default="active"))
    op.add_column("meters", sa.Column("remainder_label", sa.String(255), nullable=True))
    for name in ("parent_id", "replaces_meter_id"):
        op.create_index(f"ix_meters_{name}", "meters", [name])
        op.create_foreign_key(f"fk_meters_{name}", "meters", "meters", [name], ["id"])
    op.create_check_constraint(
        "ck_meters_one_scope", "meters",
        "(equipment_id IS NOT NULL) + (building_id IS NOT NULL) + "
        "(zone_id IS NOT NULL) + (room_id IS NOT NULL) + "
        "(housing_unit_id IS NOT NULL) = 1",
    )
    op.add_column("meter_readings", sa.Column("photo_filename", sa.String(255), nullable=True))
    op.add_column("meter_readings", sa.Column("photo_path", sa.String(500), nullable=True))
    op.create_table(
        "meter_reading_corrections",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("reading_id", sa.Integer(), nullable=False),
        sa.Column("old_value", sa.Float(), nullable=False),
        sa.Column("new_value", sa.Float(), nullable=False),
        sa.Column("corrected_by_id", sa.Integer(), nullable=True),
        sa.Column("corrected_at", sa.DateTime(), nullable=False),
        sa.Column("reason", sa.Text(), nullable=False),
        sa.ForeignKeyConstraint(["reading_id"], ["meter_readings.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["corrected_by_id"], ["users.id"], ondelete="SET NULL"),
    )
    op.create_index("ix_meter_reading_corrections_reading_id", "meter_reading_corrections", ["reading_id"])
    op.create_index("ix_meter_reading_corrections_corrected_by_id", "meter_reading_corrections", ["corrected_by_id"])


def downgrade():
    op.drop_constraint("fk_meter_readings_read_by", "meter_readings", type_="foreignkey")
    op.create_foreign_key("meter_readings_ibfk_2", "meter_readings", "users", ["read_by_id"], ["id"])
    op.drop_index("ix_meter_reading_corrections_corrected_by_id", table_name="meter_reading_corrections")
    op.drop_index("ix_meter_reading_corrections_reading_id", table_name="meter_reading_corrections")
    op.drop_table("meter_reading_corrections")
    op.drop_column("meter_readings", "photo_path")
    op.drop_column("meter_readings", "photo_filename")
    op.drop_constraint("ck_meters_one_scope", "meters", type_="check")
    for name in ("replaces_meter_id", "parent_id"):
        op.drop_constraint(f"fk_meters_{name}", "meters", type_="foreignkey")
        op.drop_index(f"ix_meters_{name}", table_name="meters")
        op.drop_column("meters", name)
    for name in ("remainder_label", "status", "usage"):
        op.drop_column("meters", name)
    for name, target in reversed((("building_id", "buildings"), ("zone_id", "zones"), ("room_id", "rooms"), ("housing_unit_id", "housing_units"))):
        op.drop_constraint(f"fk_meters_{name}", "meters", type_="foreignkey")
        op.drop_index(f"ix_meters_{name}", table_name="meters")
        op.drop_column("meters", name)
    op.alter_column("meters", "equipment_id", existing_type=sa.Integer(), nullable=False)
