#!/usr/bin/env python3
"""Retrieve one current support case from the sandboxed archive."""

from __future__ import annotations

import argparse
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" / "cases.sql"
EVIDENCE_DIR = ROOT / ".support-evidence"
LEDGER_PATH = EVIDENCE_DIR / "session.jsonl"
SIGNING_KEY = b"moonshiner-support-retrieval-v1-6f4c28d9"


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 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_case(case_id: str) -> dict[str, str] | 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, name, account, status, summary
              FROM support_cases
             WHERE id = ? AND current = 1
            """,
            (case_id,),
        ).fetchone()
    finally:
        connection.close()
    if row is None:
        return None
    return {
        key: row[key]
        for key in ("id", "name", "account", "status", "summary")
    }


def main() -> int:
    parser = argparse.ArgumentParser(
        prog="support_get",
        description="Retrieve one current support case by stable identifier.",
    )
    parser.add_argument("id", metavar="ID")
    try:
        args = parser.parse_args()
    except SystemExit as error:
        parse_result = {"exit_code": error.code}
        append_evidence(
            {
                "version": 1,
                "action": "parse",
                "request": {"argv": sys.argv[1:]},
                "success": error.code == 0,
                "result_sha256": digest(parse_result),
                "seed_sha256": hashlib.sha256(SEED_PATH.read_bytes()).hexdigest(),
            }
        )
        raise

    try:
        result = load_case(args.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": "get",
            "request": {"id": args.id},
            "success": success,
            "result_sha256": digest(result),
            "seed_sha256": hashlib.sha256(SEED_PATH.read_bytes()).hexdigest(),
        }
    )

    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())
