#!/usr/bin/env bash
set -euo pipefail

# Restores a Teleo SQLite backup into a disposable local Postgres container and
# compares source/target table row counts. It does not touch GCP or production.

SQLITE_BACKUP="${SQLITE_BACKUP:-}"
POSTGRES_IMAGE="${POSTGRES_IMAGE:-postgres:16-alpine}"
OUTPUT_ROOT="${OUTPUT_ROOT:-./outputs/gcp-infra-hardening-20260707/private-restore-canaries}"
PROOF_ROOT="${PROOF_ROOT:-./outputs/gcp-infra-hardening-20260707/proofs}"
TS="${TS:-$(date -u +%Y%m%dT%H%M%SZ)}"
SCHEMA="${SCHEMA:-teleo_restore}"
CONTAINER_NAME="${CONTAINER_NAME:-teleo-pg-restore-canary-${TS}}"

if [[ -z "$SQLITE_BACKUP" ]]; then
  echo "SQLITE_BACKUP is required, for example SQLITE_BACKUP=outputs/.../teleo-pipeline-sqlite-...db.gz" >&2
  exit 2
fi

if [[ ! -f "$SQLITE_BACKUP" ]]; then
  echo "SQLite backup not found: $SQLITE_BACKUP" >&2
  exit 2
fi

mkdir -p "$OUTPUT_ROOT" "$PROOF_ROOT"
chmod 700 "$OUTPUT_ROOT"

WORK_DIR="$OUTPUT_ROOT/sqlite-postgres-restore-canary-${TS}"
mkdir -p "$WORK_DIR"
chmod 700 "$WORK_DIR"

IMPORT_SQL="$WORK_DIR/teleo-pipeline-postgres-import.sql"
SOURCE_SUMMARY="$WORK_DIR/source-summary.json"
TARGET_COUNTS_SQL="$WORK_DIR/target-counts.sql"
TARGET_COUNTS_CSV="$WORK_DIR/target-counts.csv"
IMPORT_LOG="$WORK_DIR/postgres-import.log"
PROOF_JSON="$PROOF_ROOT/sqlite-postgres-restore-canary-${TS}.json"

cleanup() {
  if [[ "${KEEP_CONTAINER:-0}" != "1" ]]; then
    docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
  fi
}
trap cleanup EXIT

python3 ops/sqlite_to_postgres_dump.py \
  --sqlite-backup "$SQLITE_BACKUP" \
  --output-sql "$IMPORT_SQL" \
  --summary-json "$SOURCE_SUMMARY" \
  --schema "$SCHEMA" \
  --target-counts-sql "$TARGET_COUNTS_SQL"

docker run --rm -d \
  --name "$CONTAINER_NAME" \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=teleo_restore_canary \
  "$POSTGRES_IMAGE" >/dev/null

for _ in $(seq 1 60); do
  if docker exec "$CONTAINER_NAME" pg_isready -U postgres -d teleo_restore_canary >/dev/null 2>&1; then
    break
  fi
  sleep 1
done

docker exec "$CONTAINER_NAME" pg_isready -U postgres -d teleo_restore_canary >/dev/null

docker exec -i "$CONTAINER_NAME" \
  psql -v ON_ERROR_STOP=1 -U postgres -d teleo_restore_canary \
  < "$IMPORT_SQL" > "$IMPORT_LOG"

docker exec -i "$CONTAINER_NAME" \
  psql -v ON_ERROR_STOP=1 -U postgres -d teleo_restore_canary \
  < "$TARGET_COUNTS_SQL" > "$TARGET_COUNTS_CSV"

python3 - "$SOURCE_SUMMARY" "$TARGET_COUNTS_CSV" "$PROOF_JSON" "$SQLITE_BACKUP" "$IMPORT_SQL" "$POSTGRES_IMAGE" <<'PY'
import csv
import hashlib
import json
import sys
from datetime import UTC, datetime
from pathlib import Path

source_summary_path = Path(sys.argv[1])
target_counts_path = Path(sys.argv[2])
proof_path = Path(sys.argv[3])
sqlite_backup = Path(sys.argv[4])
import_sql = Path(sys.argv[5])
postgres_image = sys.argv[6]

source_summary = json.loads(source_summary_path.read_text())
source_counts = {table["name"]: int(table["row_count"]) for table in source_summary["tables"]}
with target_counts_path.open(newline="") as handle:
    target_counts = {row["table_name"]: int(row["row_count"]) for row in csv.DictReader(handle)}

all_tables = sorted(set(source_counts) | set(target_counts))
mismatches = [
    {
        "table": table,
        "source_rows": source_counts.get(table),
        "target_rows": target_counts.get(table),
    }
    for table in all_tables
    if source_counts.get(table) != target_counts.get(table)
]

def sha256(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()

proof = {
    "artifact": "sqlite_postgres_restore_canary",
    "generated_at_utc": datetime.now(UTC).isoformat(),
    "status": "pass" if not mismatches and source_summary["source_integrity_check"] == "ok" else "fail",
    "source_sqlite_backup": str(sqlite_backup),
    "source_sqlite_backup_sha256": sha256(sqlite_backup),
    "postgres_image": postgres_image,
    "source_integrity_check": source_summary["source_integrity_check"],
    "postgres_schema": source_summary["schema"],
    "source_table_count": len(source_counts),
    "target_table_count": len(target_counts),
    "source_total_rows": sum(source_counts.values()),
    "target_total_rows": sum(target_counts.values()),
    "mismatched_tables": mismatches,
    "conversion_notes": source_summary["conversion_notes"],
    "conversion_stats": source_summary["conversion_stats"],
    "private_artifacts": {
        "source_summary_json": str(source_summary_path),
        "postgres_import_sql": str(import_sql),
        "target_counts_csv": str(target_counts_path),
    },
}
proof_path.write_text(json.dumps(proof, indent=2, sort_keys=True) + "\n")
print(json.dumps(proof, indent=2, sort_keys=True))
sys.exit(0 if proof["status"] == "pass" else 1)
PY
