#!/usr/bin/env python3
"""
Migration: Add device_model column to monitoring_sessions table.

Records which physical SLM model produced each session's data (e.g. "NL-43",
"NL-53", "NL-32"). Used by report generation to apply the correct parsing
logic without re-opening files to detect format.

Run once inside the Docker container:
    docker exec terra-view python3 backend/migrate_add_session_device_model.py

Backfill strategy for existing rows:
  1. If session.unit_id is set, use roster.slm_model for that unit.
  2. Else, peek at the first .rnd file in the session: presence of the 'LAeq'
     column header identifies AU2 / NL-32 format.
  Sessions where neither hint is available remain NULL — the file-content
  fallback in report code handles them transparently.
"""
import csv
import io
from pathlib import Path

DB_PATH = Path("data/seismo_fleet.db")


def _peek_first_row(abs_path: Path) -> dict:
    """Read only the header + first data row of an RND file. Very cheap."""
    try:
        with open(abs_path, "r", encoding="utf-8", errors="replace") as f:
            reader = csv.DictReader(f)
            return next(reader, None) or {}
    except Exception:
        return {}


def _detect_model_from_rnd(abs_path: Path) -> str | None:
    """Return 'NL-32' if file uses AU2 column format, else None."""
    row = _peek_first_row(abs_path)
    if "LAeq" in row:
        return "NL-32"
    return None


def migrate():
    import sqlite3

    if not DB_PATH.exists():
        print(f"Database not found at {DB_PATH}. Are you running from /home/serversdown/terra-view?")
        return

    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    cur = conn.cursor()

    # ── 1. Add column (idempotent) ───────────────────────────────────────────
    cur.execute("PRAGMA table_info(monitoring_sessions)")
    existing_cols = {row["name"] for row in cur.fetchall()}

    if "device_model" not in existing_cols:
        cur.execute("ALTER TABLE monitoring_sessions ADD COLUMN device_model TEXT")
        conn.commit()
        print("✓ Added column device_model to monitoring_sessions")
    else:
        print("○ Column device_model already exists — skipping ALTER TABLE")

    # ── 2. Backfill existing NULL rows ───────────────────────────────────────
    cur.execute(
        "SELECT id, unit_id FROM monitoring_sessions WHERE device_model IS NULL"
    )
    sessions = cur.fetchall()
    print(f"Backfilling {len(sessions)} session(s) with device_model=NULL...")

    updated = skipped = 0
    for row in sessions:
        session_id = row["id"]
        unit_id = row["unit_id"]
        device_model = None

        # Strategy A: look up unit's slm_model from the roster
        if unit_id:
            cur.execute(
                "SELECT slm_model FROM roster WHERE id = ?", (unit_id,)
            )
            unit_row = cur.fetchone()
            if unit_row and unit_row["slm_model"]:
                device_model = unit_row["slm_model"]

        # Strategy B: detect from first .rnd file in the session
        if device_model is None:
            cur.execute(
                """SELECT file_path FROM data_files
                   WHERE session_id = ?
                   AND lower(file_path) LIKE '%.rnd'
                   LIMIT 1""",
                (session_id,),
            )
            file_row = cur.fetchone()
            if file_row:
                abs_path = Path("data") / file_row["file_path"]
                device_model = _detect_model_from_rnd(abs_path)
                # None here means NL-43/NL-53 format (or unreadable file) —
                # leave as NULL so the existing fallback applies.

        if device_model:
            cur.execute(
                "UPDATE monitoring_sessions SET device_model = ? WHERE id = ?",
                (device_model, session_id),
            )
            updated += 1
        else:
            skipped += 1

    conn.commit()
    conn.close()

    print(f"✓ Backfilled {updated} session(s) with a device_model.")
    if skipped:
        print(
            f"  {skipped} session(s) left as NULL "
            "(no unit link and no AU2 file hint — NL-43/NL-53 or unknown; "
            "file-content detection applies at report time)."
        )
    print("Migration complete.")


if __name__ == "__main__":
    migrate()
