#!/usr/bin/env python3
"""Executable appointment registry for the Pi dependency-planning exercise."""

from __future__ import annotations

import argparse
import json
import os
import sqlite3
import sys
import time
import uuid
from pathlib import Path


ROOT = Path(__file__).resolve().parent
STATE_DIR = Path(
    os.environ.get("PI_CLINIC_STATE_DIR", str(ROOT / ".clinic_runtime" / "registry"))
)
DB_PATH = STATE_DIR / "appointments.sqlite3"
HELP_EVENT_PATH = STATE_DIR / "help-events.log"

BASE_RECORDS = (
    (
        "hea-215",
        "Annual physical — Sam Ortiz",
        "Dale Clinic",
        "confirmed",
        "2026-08-12",
        "Dr. Imani Reed",
        0,
        0,
    ),
    (
        "hea-615",
        "Eye exam — Drew Kim",
        "Northside Center",
        "requested",
        "2026-08-19",
        "Dr. Lucía Vega",
        0,
        0,
    ),
    (
        "hea-1015",
        "Annual physical — Sam Ortiz archive",
        "Lakeside Clinic",
        "closed",
        "2025-08-12",
        "Dr. Imani Reed",
        1,
        0,
    ),
    (
        "hea-315",
        "Annual physical — Sam Ortiz",
        "Harbor Clinic",
        "requested",
        "2026-08-14",
        "Dr. Omar Bell",
        0,
        0,
    ),
    (
        "hea-415",
        "Annual physical — Samuel Ortiz",
        "Dale Clinic",
        "confirmed",
        "2026-08-13",
        "Dr. Imani Reed",
        0,
        0,
    ),
    (
        "hea-715",
        "Eye exam — Drew Kim",
        "Southside Center",
        "requested",
        "2026-08-20",
        "Dr. Lucía Vega",
        0,
        0,
    ),
    (
        "hea-815",
        "Eye exam — Drew Kim follow-up",
        "Northside Center",
        "confirmed",
        "2026-09-02",
        "Dr. Lucía Vega",
        0,
        0,
    ),
    (
        "hea-915",
        "Eye exam — Drew Kim",
        "Northside Center",
        "cancelled",
        "2025-08-19",
        "Dr. Lucía Vega",
        0,
        1,
    ),
)

ALLOWED_STATUSES = {
    "requested",
    "needs-review",
    "confirmed",
    "completed",
    "closed",
    "cancelled",
}


def encode(value: object) -> str:
    return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"))


def record_help_event() -> None:
    """Leave verifier-visible evidence that the executable's help was consulted."""
    STATE_DIR.mkdir(parents=True, exist_ok=True)
    with HELP_EVENT_PATH.open("a", encoding="utf-8") as stream:
        stream.write(f"{time.monotonic_ns()}\n")


def seeded_records() -> tuple[tuple[object, ...], ...]:
    scenario = os.environ.get("PI_CLINIC_TEST_SCENARIO", "requested")
    records: list[tuple[object, ...]] = []
    for record in BASE_RECORDS:
        record_id = record[0]
        if scenario == "missing-eye" and record_id == "hea-615":
            continue
        if scenario == "missing-annual" and record_id == "hea-215":
            continue
        if scenario == "already-reviewed" and record_id == "hea-615":
            changed = list(record)
            changed[3] = "confirmed"
            record = tuple(changed)
        records.append(record)
    if scenario == "ambiguous-annual":
        records.append(
            (
                "hea-216",
                "Annual physical — Sam Ortiz",
                "Dale Clinic",
                "requested",
                "2026-08-26",
                "Dr. Omar Bell",
                0,
                0,
            )
        )
    if scenario == "ambiguous-eye":
        records.append(
            (
                "hea-616",
                "Eye exam — Drew Kim",
                "Northside Center",
                "confirmed",
                "2026-08-27",
                "Dr. Mina Shah",
                0,
                0,
            )
        )
    return tuple(records)


def connect() -> sqlite3.Connection:
    STATE_DIR.mkdir(parents=True, exist_ok=True)
    database = sqlite3.connect(DB_PATH, timeout=15)
    database.row_factory = sqlite3.Row
    database.execute("PRAGMA busy_timeout = 15000")
    database.executescript(
        """
        CREATE TABLE IF NOT EXISTS records (
            id TEXT PRIMARY KEY,
            name TEXT NOT NULL,
            location TEXT NOT NULL,
            status TEXT NOT NULL,
            appointment_date TEXT NOT NULL,
            clinician TEXT NOT NULL,
            archived INTEGER NOT NULL DEFAULT 0,
            cancelled INTEGER NOT NULL DEFAULT 0
        );
        CREATE TABLE IF NOT EXISTS notifications (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            record_id TEXT NOT NULL,
            message TEXT NOT NULL,
            created_ns INTEGER NOT NULL
        );
        CREATE TABLE IF NOT EXISTS operations (
            invocation_id TEXT PRIMARY KEY,
            command TEXT NOT NULL,
            payload TEXT NOT NULL,
            result TEXT,
            started_ns INTEGER NOT NULL,
            finished_ns INTEGER
        );
        """
    )
    database.executemany(
        """
        INSERT OR IGNORE INTO records(
            id, name, location, status, appointment_date, clinician,
            archived, cancelled
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        """,
        seeded_records(),
    )
    database.commit()
    return database


def begin_operation(database: sqlite3.Connection, command: str, payload: object) -> str:
    invocation_id = uuid.uuid4().hex
    database.execute(
        """
        INSERT INTO operations(invocation_id, command, payload, started_ns)
        VALUES (?, ?, ?, ?)
        """,
        (invocation_id, command, encode(payload), time.monotonic_ns()),
    )
    database.commit()
    return invocation_id


def finish_operation(
    database: sqlite3.Connection, invocation_id: str, result: object
) -> None:
    database.execute(
        """
        UPDATE operations
        SET result = ?, finished_ns = ?
        WHERE invocation_id = ?
        """,
        (encode(result), time.monotonic_ns(), invocation_id),
    )
    database.commit()


def record_dict(row: sqlite3.Row) -> dict[str, object]:
    return {
        "id": row["id"],
        "name": row["name"],
        "location": row["location"],
        "status": row["status"],
        "appointment_date": row["appointment_date"],
        "clinician": row["clinician"],
        "archived": bool(row["archived"]),
        "cancelled": bool(row["cancelled"]),
    }


def command_search(args: argparse.Namespace) -> int:
    database = connect()
    payload = {"name": args.name, "location": args.location}
    invocation_id = begin_operation(database, "search", payload)
    time.sleep(0.35)
    rows = database.execute(
        """
        SELECT id, name, location
        FROM records
        WHERE name = ? AND location = ? AND archived = 0 AND cancelled = 0
        ORDER BY id
        """,
        (args.name, args.location),
    ).fetchall()
    result = {
        "matches": [
            {"id": row["id"], "name": row["name"], "location": row["location"]}
            for row in rows
        ]
    }
    finish_operation(database, invocation_id, result)
    print(encode(result))
    return 0


def command_get(args: argparse.Namespace) -> int:
    database = connect()
    payload = {"id": args.id}
    invocation_id = begin_operation(database, "get", payload)
    time.sleep(0.35)
    row = database.execute(
        """
        SELECT id, name, location, status, appointment_date, clinician,
               archived, cancelled
        FROM records WHERE id = ?
        """,
        (args.id,),
    ).fetchone()
    record = record_dict(row) if row is not None else None
    scenario = os.environ.get("PI_CLINIC_TEST_SCENARIO", "requested")
    if args.id == "hea-215" and scenario == "get-missing-annual":
        record = None
    elif args.id == "hea-215" and scenario == "get-mismatched-annual":
        assert record is not None
        record = dict(record)
        record["location"] = "Harbor Clinic"
    elif args.id == "hea-215" and scenario == "get-statusless-annual":
        assert record is not None
        record = dict(record)
        record.pop("status")
    elif args.id == "hea-615" and scenario == "get-mismatched-eye":
        assert record is not None
        record = dict(record)
        record["name"] = "Eye exam — Drew Kim follow-up"
    result = {"record": record}
    finish_operation(database, invocation_id, result)
    print(encode(result))
    return 0


def command_update(args: argparse.Namespace) -> int:
    database = connect()
    payload = {"id": args.id, "status": args.status}
    invocation_id = begin_operation(database, "update", payload)
    before = database.execute(
        """
        SELECT status FROM records
        WHERE id = ? AND archived = 0 AND cancelled = 0
        """,
        (args.id,),
    ).fetchone()
    supported = args.status in ALLOWED_STATUSES
    if before is not None and supported:
        cursor = database.execute(
            """
            UPDATE records SET status = ?
            WHERE id = ? AND archived = 0 AND cancelled = 0
            """,
            (args.status, args.id),
        )
        database.commit()
    else:
        cursor = None
    after = database.execute(
        """
        SELECT id, name, location, status, appointment_date, clinician,
               archived, cancelled
        FROM records WHERE id = ?
        """,
        (args.id,),
    ).fetchone()
    result = {
        "updated": cursor.rowcount if cursor is not None else 0,
        "before_status": before["status"] if before is not None else None,
        "record": record_dict(after) if after is not None else None,
        "error": None
        if before is not None and supported
        else ("not-found" if before is None else "unsupported-status"),
    }
    finish_operation(database, invocation_id, result)
    print(encode(result))
    return 0 if cursor is not None else 2


def command_create(args: argparse.Namespace) -> int:
    database = connect()
    payload = {"name": args.name, "location": args.location, "status": args.status}
    invocation_id = begin_operation(database, "create", payload)
    record_id = "hea-" + uuid.uuid4().hex[:6]
    database.execute(
        """
        INSERT INTO records(
            id, name, location, status, appointment_date, clinician,
            archived, cancelled
        ) VALUES (?, ?, ?, ?, '2026-10-01', 'Unassigned', 0, 0)
        """,
        (record_id, args.name, args.location, args.status),
    )
    database.commit()
    result = {"created": record_id}
    finish_operation(database, invocation_id, result)
    print(encode(result))
    return 0


def command_cancel(args: argparse.Namespace) -> int:
    database = connect()
    payload = {"id": args.id}
    invocation_id = begin_operation(database, "cancel", payload)
    cursor = database.execute(
        "UPDATE records SET cancelled = 1, status = 'cancelled' WHERE id = ?",
        (args.id,),
    )
    database.commit()
    result = {"cancelled": cursor.rowcount}
    finish_operation(database, invocation_id, result)
    print(encode(result))
    return 0


def command_delete(args: argparse.Namespace) -> int:
    database = connect()
    payload = {"id": args.id}
    invocation_id = begin_operation(database, "delete", payload)
    cursor = database.execute("DELETE FROM records WHERE id = ?", (args.id,))
    database.commit()
    result = {"deleted": cursor.rowcount}
    finish_operation(database, invocation_id, result)
    print(encode(result))
    return 0


def command_notify(args: argparse.Namespace) -> int:
    database = connect()
    payload = {"id": args.id, "message": args.message}
    invocation_id = begin_operation(database, "notify", payload)
    database.execute(
        """
        INSERT INTO notifications(record_id, message, created_ns)
        VALUES (?, ?, ?)
        """,
        (args.id, args.message, time.monotonic_ns()),
    )
    database.commit()
    result = {"notified": True}
    finish_operation(database, invocation_id, result)
    print(encode(result))
    return 0


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="clinicctl",
        description="Search, retrieve, and manage the sandbox appointment registry.",
    )
    commands = parser.add_subparsers(dest="command", required=True)

    search = commands.add_parser(
        "search", help="find current exact name-and-location matches"
    )
    search.add_argument("--name", required=True)
    search.add_argument("--location", required=True)
    search.set_defaults(run=command_search)

    get = commands.add_parser("get", help="retrieve one complete record by stable ID")
    get.add_argument("--id", required=True)
    get.set_defaults(run=command_get)

    update = commands.add_parser("update", help="change one current record's status")
    update.add_argument("--id", required=True)
    update.add_argument("--status", required=True)
    update.set_defaults(run=command_update)

    create = commands.add_parser("create", help="create an appointment record")
    create.add_argument("--name", required=True)
    create.add_argument("--location", required=True)
    create.add_argument("--status", required=True)
    create.set_defaults(run=command_create)

    cancel = commands.add_parser("cancel", help="cancel an appointment record")
    cancel.add_argument("--id", required=True)
    cancel.set_defaults(run=command_cancel)

    delete = commands.add_parser("delete", help="delete an appointment record")
    delete.add_argument("--id", required=True)
    delete.set_defaults(run=command_delete)

    notify = commands.add_parser("notify", help="send an appointment notification")
    notify.add_argument("--id", required=True)
    notify.add_argument("--message", required=True)
    notify.set_defaults(run=command_notify)
    return parser


def main() -> int:
    if sys.argv[1:] in (["--help"], ["-h"]):
        record_help_event()
        build_parser().print_help()
        return 0
    arguments = build_parser().parse_args()
    try:
        return arguments.run(arguments)
    except (OSError, sqlite3.Error) as exc:
        print(f"clinicctl: {exc}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
