"""Add C4 copier contracts and shared consumable workflows."""
from alembic import op
import sqlalchemy as sa


revision = "s4g5h6i7j8k9"
down_revision = "r3f4g5h6i7j8"
branch_labels = None
depends_on = None


def upgrade():
    op.add_column("equipments", sa.Column("device_type", sa.String(length=30), nullable=True))
    op.add_column("equipments", sa.Column("ip_address", sa.String(length=45), nullable=True))
    op.add_column("equipments", sa.Column("hostname", sa.String(length=120), nullable=True))
    op.add_column("equipments", sa.Column("mac_address", sa.String(length=17), nullable=True))
    op.add_column("consumables", sa.Column("consumable_type", sa.String(length=30), nullable=False, server_default="OTHER"))
    op.add_column("consumables", sa.Column("target_quantity", sa.Integer(), nullable=True))
    op.create_unique_constraint("uq_equipment_consumable_pair", "equipment_consumables", ["equipment_id", "consumable_id"])

    op.create_table(
        "photocopier_contracts",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("supplier_id", sa.Integer(), sa.ForeignKey("companies.id"), nullable=False),
        sa.Column("name", sa.String(200), nullable=False),
        sa.Column("reference", sa.String(120)),
        sa.Column("start_date", sa.Date(), nullable=False),
        sa.Column("end_date", sa.Date(), nullable=False),
        sa.Column("quota_start_date", sa.Date(), nullable=True),
        sa.Column("anniversary_month", sa.Integer(), nullable=False),
        sa.Column("anniversary_day", sa.Integer(), nullable=False),
        sa.Column("status", sa.String(20), nullable=False, server_default="ACTIVE"),
        sa.Column("notes", sa.Text()),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("closed_at", sa.Date()),
        sa.CheckConstraint("end_date >= start_date", name="ck_c4_contract_dates"),
    )
    op.create_index("ix_c4_contract_supplier", "photocopier_contracts", ["supplier_id"])
    op.create_index("ix_c4_contract_status", "photocopier_contracts", ["status"])

    op.create_table(
        "photocopier_contract_periods",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("contract_id", sa.Integer(), sa.ForeignKey("photocopier_contracts.id", ondelete="CASCADE"), nullable=False),
        sa.Column("start_date", sa.Date(), nullable=False),
        sa.Column("end_date", sa.Date(), nullable=False),
        sa.Column("quota_bw", sa.Integer()),
        sa.Column("quota_color", sa.Integer()),
        sa.Column("bw_included_unit_price", sa.Numeric(12, 6)),
        sa.Column("bw_overage_unit_price", sa.Numeric(12, 6)),
        sa.Column("color_included_unit_price", sa.Numeric(12, 6)),
        sa.Column("color_overage_unit_price", sa.Numeric(12, 6)),
        sa.Column("status", sa.String(20), nullable=False, server_default="OPEN"),
        sa.CheckConstraint("end_date >= start_date", name="ck_c4_period_dates"),
        sa.CheckConstraint("(quota_bw IS NULL OR quota_bw >= 0) AND (quota_color IS NULL OR quota_color >= 0)", name="ck_c4_period_quotas"),
        sa.UniqueConstraint("contract_id", "start_date", name="uq_c4_contract_period_start"),
    )
    op.create_index("ix_c4_period_contract", "photocopier_contract_periods", ["contract_id"])
    op.create_index("ix_c4_period_start", "photocopier_contract_periods", ["start_date"])
    op.create_index("ix_c4_period_end", "photocopier_contract_periods", ["end_date"])

    op.create_table(
        "contract_equipment_assignments",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("contract_id", sa.Integer(), sa.ForeignKey("photocopier_contracts.id", ondelete="CASCADE"), nullable=False),
        sa.Column("equipment_id", sa.Integer(), sa.ForeignKey("equipments.id", ondelete="CASCADE"), nullable=False),
        sa.Column("entry_date", sa.Date(), nullable=False),
        sa.Column("exit_date", sa.Date()),
        sa.Column("replacement_reason", sa.String(40)),
        sa.Column("replacement_comment", sa.Text()),
        sa.CheckConstraint("exit_date IS NULL OR exit_date >= entry_date", name="ck_c4_assignment_dates"),
        sa.UniqueConstraint("contract_id", "equipment_id", "entry_date", name="uq_c4_contract_equipment_entry"),
    )
    op.create_index("ix_c4_assignment_contract", "contract_equipment_assignments", ["contract_id"])
    op.create_index("ix_c4_assignment_equipment", "contract_equipment_assignments", ["equipment_id"])

    op.create_table(
        "consumable_orders",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("consumable_id", sa.Integer(), sa.ForeignKey("consumables.id", ondelete="RESTRICT"), nullable=False),
        sa.Column("supplier_id", sa.Integer(), sa.ForeignKey("companies.id")),
        sa.Column("quantity_ordered", sa.Integer(), nullable=False),
        sa.Column("quantity_received", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("status", sa.String(30), nullable=False, server_default="TO_ORDER"),
        sa.Column("ordered_at", sa.DateTime()),
        sa.Column("received_at", sa.DateTime()),
        sa.Column("comment", sa.Text()),
        sa.Column("created_by_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL")),
        sa.CheckConstraint("quantity_ordered > 0", name="ck_c4_order_quantity"),
        sa.CheckConstraint("quantity_received >= 0 AND quantity_received <= quantity_ordered", name="ck_c4_order_received"),
    )
    op.create_index("ix_c4_order_consumable", "consumable_orders", ["consumable_id"])
    op.create_index("ix_c4_order_supplier", "consumable_orders", ["supplier_id"])
    op.create_index("ix_c4_order_status", "consumable_orders", ["status"])

    op.create_table(
        "consumable_receipts",
        sa.Column("id", sa.Integer(), primary_key=True),
        sa.Column("order_id", sa.Integer(), sa.ForeignKey("consumable_orders.id", ondelete="CASCADE"), nullable=False),
        sa.Column("quantity", sa.Integer(), nullable=False),
        sa.Column("received_at", sa.DateTime(), nullable=False),
        sa.Column("received_by_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL")),
        sa.Column("comment", sa.Text()),
    )
    op.create_index("ix_c4_receipt_order", "consumable_receipts", ["order_id"])


def downgrade():
    op.drop_table("consumable_receipts")
    op.drop_table("consumable_orders")
    op.drop_table("contract_equipment_assignments")
    op.drop_table("photocopier_contract_periods")
    op.drop_table("photocopier_contracts")
    op.drop_constraint("uq_equipment_consumable_pair", "equipment_consumables", type_="unique")
    op.drop_column("consumables", "target_quantity")
    op.drop_column("consumables", "consumable_type")
    op.drop_column("equipments", "mac_address")
    op.drop_column("equipments", "hostname")
    op.drop_column("equipments", "ip_address")
    op.drop_column("equipments", "device_type")
