#!/usr/bin/env python3
"""
sbin/migrate_parent_key.py
==========================
Adds parent_key column, changes uniqueness from UNIQUE(name) to
UNIQUE(parent_key, name), and clears device_type/location for sub-components.

SQLite: recreates the device table (required to change constraints).
MariaDB: uses ALTER TABLE. Check the index name with:
    SHOW INDEX FROM device WHERE Column_name = 'name';

Usage:
    python sbin/migrate_parent_key.py               # SQLite (batteries.db)
    MARIADB_URL='mysql+...' python sbin/migrate_parent_key.py
"""

import os
import shutil
import sys
from datetime import date
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent


def snapshot(src: Path) -> None:
    dst = src.parent / f"{src.name}.{date.today().isoformat()}.snapshot"
    shutil.copy2(src, dst)
    print(f"Snapshot: {dst.name}")


def migrate_sqlite() -> None:
    import sqlite3

    db_path = REPO_ROOT / "batteries.db"
    if not db_path.exists():
        print("batteries.db not found — nothing to migrate.")
        return

    snapshot(db_path)
    conn = sqlite3.connect(str(db_path))
    conn.execute("PRAGMA foreign_keys = OFF")

    # Check if parent_key already exists (idempotency)
    cols = {row[1] for row in conn.execute("PRAGMA table_info(device)")}
    if "parent_key" in cols:
        print("parent_key already present — running data-only fixup.")
        conn.execute("UPDATE device SET parent_key = COALESCE(parent_id, -1)")
        conn.execute("UPDATE device SET device_type = NULL, location = NULL WHERE parent_id IS NOT NULL")
        conn.commit()
        conn.close()
        print("Done.")
        return

    conn.execute("ALTER TABLE device RENAME TO device_old")

    conn.execute("""
        CREATE TABLE device (
            id           INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            name         VARCHAR(100) NOT NULL,
            battery_slots INTEGER NOT NULL DEFAULT 1,
            device_type  VARCHAR(50),
            battery_size VARCHAR(20),
            location     VARCHAR(100),
            notes        TEXT,
            ha_entity_id VARCHAR(100),
            parent_id    INTEGER REFERENCES device(id) ON DELETE SET NULL,
            parent_key   INTEGER NOT NULL DEFAULT -1,
            CONSTRAINT uq_device_parent_key_name UNIQUE (parent_key, name)
        )
    """)

    conn.execute("""
        INSERT INTO device
            (id, name, battery_slots, device_type, battery_size, location,
             notes, ha_entity_id, parent_id, parent_key)
        SELECT
            id, name, battery_slots,
            CASE WHEN parent_id IS NOT NULL THEN NULL ELSE device_type END,
            battery_size,
            CASE WHEN parent_id IS NOT NULL THEN NULL ELSE location END,
            notes, ha_entity_id, parent_id,
            COALESCE(parent_id, -1)
        FROM device_old
    """)

    conn.execute("DROP TABLE device_old")
    conn.execute("PRAGMA foreign_keys = ON")
    conn.commit()

    count = conn.execute("SELECT COUNT(*) FROM device").fetchone()[0]
    print(f"SQLite migration complete — {count} device(s) migrated.")
    conn.close()


def migrate_mariadb(url: str) -> None:
    from sqlalchemy import create_engine, text

    engine = create_engine(url)
    with engine.connect() as conn:
        # Add column (skip if already present)
        try:
            conn.execute(text(
                "ALTER TABLE device ADD COLUMN parent_key INT NOT NULL DEFAULT -1"
            ))
        except Exception:
            print("parent_key column already exists — skipping ADD COLUMN.")

        conn.execute(text("UPDATE device SET parent_key = COALESCE(parent_id, -1)"))
        conn.execute(text(
            "UPDATE device SET device_type = NULL, location = NULL WHERE parent_id IS NOT NULL"
        ))

        # Drop old UNIQUE index on name — check actual name first:
        #   SHOW INDEX FROM device WHERE Column_name = 'name';
        # Common names: 'name' or 'ix_device_name'
        for idx_name in ("name", "ix_device_name"):
            try:
                conn.execute(text(f"ALTER TABLE device DROP INDEX `{idx_name}`"))
                print(f"Dropped index '{idx_name}'.")
                break
            except Exception:
                continue

        conn.execute(text(
            "ALTER TABLE device ADD CONSTRAINT uq_device_parent_key_name "
            "UNIQUE (parent_key, name)"
        ))
        conn.commit()

    print("MariaDB migration complete.")


if __name__ == "__main__":
    mariadb_url = os.environ.get("MARIADB_URL", "").strip()
    if mariadb_url:
        migrate_mariadb(mariadb_url)
    else:
        migrate_sqlite()
