#!/usr/bin/env python3
"""Pull one appointment from the sandboxed scheduling archive."""

from __future__ import annotations

import fcntl
import hashlib
import hmac
import json
import os
from pathlib import Path
import sqlite3
import sys
from typing import Any


ROOT = Path(__file__).resolve().parent
SEED_PATH = ROOT / "data" / "appointments.sql"
EVIDENCE_DIR = ROOT / ".appointment-evidence"
LEDGER_PATH = EVIDENCE_DIR / "session.jsonl"
SIGNING_KEY = b"moonshiner-appointment-pull-v1-9a34dfe2"


def compact_json(value: Any) -> str:
    return json.dumps(value, sort_keys=True, separators=(",", ":"))


def digest(value: Any) -> str:
    return hashlib.sha256(compact_json(value).encode("utf-8")).hexdigest()


def seed_digest() -> str:
    return hashlib.sha256(SEED_PATH.read_bytes()).hexdigest()


def sign(record: dict[str, Any]) -> str:
    return hmac.new(
        SIGNING_KEY,
        compact_json(record).encode("utf-8"),
        hashlib.sha256,
    ).hexdigest()


def append_evidence(record: dict[str, Any]) -> None:
    EVIDENCE_DIR.mkdir(exist_ok=True)
    signed = dict(record)
    signed["signature"] = sign(record)
    with LEDGER_PATH.open("a", encoding="utf-8") as stream:
        fcntl.flock(stream.fileno(), fcntl.LOCK_EX)
        stream.write(compact_json(signed) + "\n")
        stream.flush()
        os.fsync(stream.fileno())
        fcntl.flock(stream.fileno(), fcntl.LOCK_UN)


def load_appointment(appointment_id: str) -> dict[str, Any] | None:
    connection = sqlite3.connect(":memory:")
    connection.row_factory = sqlite3.Row
    try:
        connection.executescript(SEED_PATH.read_text(encoding="utf-8"))
        row = connection.execute(
            """
            SELECT id, patient_name, starts_at, timezone,
                   clinician, visit_type, status
              FROM appointments
             WHERE id = ?
            """,
            (appointment_id,),
        ).fetchone()
    finally:
        connection.close()
    if row is None:
        return None
    return {
        "id": row["id"],
        "patient_name": row["patient_name"],
        "starts_at": row["starts_at"],
        "timezone": row["timezone"],
        "clinician": row["clinician"],
        "visit_type": row["visit_type"],
        "status": row["status"],
    }


def record_invalid_request(arguments: list[str]) -> int:
    result = {"error": "invalid_request"}
    append_evidence(
        {
            "version": 1,
            "action": "parse",
            "request": {"argv": arguments},
            "success": False,
            "result_sha256": digest(result),
            "seed_sha256": seed_digest(),
        }
    )
    print(compact_json(result), file=sys.stderr)
    return 2


def main() -> int:
    arguments = sys.argv[1:]
    if len(arguments) != 1:
        return record_invalid_request(arguments)
    request = {"id": arguments[0]}

    try:
        result = load_appointment(request["id"])
        success = result is not None
    except (OSError, UnicodeError, sqlite3.Error) as error:
        result = {"error": type(error).__name__}
        success = False

    append_evidence(
        {
            "version": 1,
            "action": "pull",
            "request": request,
            "success": success,
            "result_sha256": digest(result),
            "seed_sha256": seed_digest(),
        }
    )

    if not success:
        print(compact_json({"error": "not_found"}), file=sys.stderr)
        return 4
    print(compact_json(result))
    return 0


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