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

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"

profile="detection-cpu"
cmvr_es_root="${PROJECT_ROOT}/../cmvr-es"
skip_codegen=false
skip_check=false

verify_model_artifact() {
  local model_id="$1"
  local relative_path="$2"
  local expected_size="$3"
  local expected_sha256="$4"
  local artifact_path="${PROJECT_ROOT}/${relative_path}"

  if [[ ! -f "${artifact_path}" ]]; then
    echo "error: model artifact is missing for ${model_id}: ${relative_path}" >&2
    echo "restore the model file before using the ${profile} profile" >&2
    exit 1
  fi

  if LC_ALL=C grep -q -F "version https://git-lfs.github.com/spec/v1" "${artifact_path}"; then
    echo "error: model artifact is only a Git LFS pointer: ${relative_path}" >&2
    echo "run 'git lfs pull' to fetch the real model weights" >&2
    exit 1
  fi

  local actual_size
  actual_size="$(wc -c < "${artifact_path}")"
  actual_size="${actual_size//[[:space:]]/}"
  if [[ "${actual_size}" != "${expected_size}" ]]; then
    echo "error: model artifact size mismatch for ${model_id}: ${relative_path}" >&2
    echo "expected ${expected_size} bytes, got ${actual_size} bytes" >&2
    exit 1
  fi

  local actual_sha256
  actual_sha256="$(sha256sum "${artifact_path}" | awk '{print $1}')"
  if [[ "${actual_sha256}" != "${expected_sha256}" ]]; then
    echo "error: model artifact checksum mismatch for ${model_id}: ${relative_path}" >&2
    echo "expected SHA256 ${expected_sha256}, got ${actual_sha256}" >&2
    exit 1
  fi
}

usage() {
  cat <<'EOF'
Usage: bash scripts/bootstrap.sh [options]

Create the locked uv environment, optionally generate cmvr-es Python bindings,
and run basic health checks.

Options:
  --profile PROFILE     core, detection-cpu (default), or dev
  --cmvr-es-root PATH   cmvr-es checkout (default: sibling ../cmvr-es)
  --skip-codegen        do not generate cmvr-es protobuf/gRPC bindings
  --skip-check          install only; skip validation and tests
  -h, --help            show this help

Profiles:
  core            framework, minimal fixture, and simulated talk pipeline only
  detection-cpu   gRPC + HTTP + PyAV + locked CPU YOLO runtime
  dev             detection-cpu plus tests and portable protobuf codegen tools
EOF
}

while (($#)); do
  case "$1" in
    --profile)
      if (($# < 2)); then
        echo "error: --profile requires a value" >&2
        exit 2
      fi
      profile="$2"
      shift 2
      ;;
    --cmvr-es-root)
      if (($# < 2)); then
        echo "error: --cmvr-es-root requires a path" >&2
        exit 2
      fi
      cmvr_es_root="$2"
      shift 2
      ;;
    --skip-codegen)
      skip_codegen=true
      shift
      ;;
    --skip-check)
      skip_check=true
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "error: unknown argument: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

case "${profile}" in
  core)
    sync_args=(--locked --no-default-groups)
    needs_cmvr_bindings=false
    ;;
  detection-cpu)
    sync_args=(
      --locked
      --no-default-groups
      --extra grpc
      --extra http
      --extra video
      --extra image
      --extra yolo-cpu
    )
    needs_cmvr_bindings=true
    ;;
  dev)
    sync_args=(
      --locked
      --no-default-groups
      --group dev
      --extra grpc
      --extra http
      --extra video
      --extra image
      --extra yolo-cpu
    )
    needs_cmvr_bindings=true
    ;;
  *)
    echo "error: unsupported profile '${profile}'" >&2
    echo "expected one of: core, detection-cpu, dev" >&2
    exit 2
    ;;
esac

if ! command -v uv >/dev/null 2>&1; then
  echo "error: uv is not installed or not available on PATH" >&2
  echo "see https://docs.astral.sh/uv/getting-started/installation/" >&2
  exit 1
fi

cd "${PROJECT_ROOT}"
echo "==> project: ${PROJECT_ROOT}"
echo "==> profile: ${profile}"

if [[ "${needs_cmvr_bindings}" == true && "${skip_codegen}" == false ]]; then
  if [[ ! -d "${cmvr_es_root}/protos/cmvr" ]]; then
    echo "error: cmvr-es protos were not found under: ${cmvr_es_root}" >&2
    echo "pass --cmvr-es-root PATH or use --skip-codegen with existing bindings" >&2
    exit 1
  fi

  echo "==> installing the locked protobuf codegen environment"
  uv sync --locked --only-group codegen
  echo "==> generating cmvr-es Python bindings from ${cmvr_es_root}"
  .venv/bin/python scripts/generate_cmvr_stubs.py \
    --cmvr-es-root "${cmvr_es_root}" \
    --portable
fi

echo "==> installing the locked ${profile} environment"
uv sync "${sync_args[@]}"

if [[ "${skip_check}" == true ]]; then
  echo "==> installation complete (checks skipped)"
  exit 0
fi

echo "==> validating the minimal framework fixture"
.venv/bin/cmvr-edge-ai validate \
  --config tests/fixtures/minimal_pipeline.yaml \
  --pipeline minimal

echo "==> validating the merged talk pipeline"
.venv/bin/cmvr-edge-ai validate \
  --config configs/edge_ai.yaml \
  --pipeline talk

if [[ "${needs_cmvr_bindings}" == true ]]; then
  echo "==> verifying detection model artifacts"
  verify_model_artifact \
    "construction-ppe-yolov8@1" \
    "models/detection/construction-ppe-yolov8/v1/best.pt" \
    "22537898" \
    "31ef3ca04a17cf545f3fcfc64c4af8993a41d52ccc460e82aff01d5354603533"
  verify_model_artifact \
    "ppe-6classes-yolov8n@1" \
    "models/detection/ppe-6classes-yolov8n/v1/best.pt" \
    "5625014" \
    "07172ef3ae9e256c40a1fb0ce3eefe5547d90170645aa73dded0fffc382cdb31"

  echo "==> checking detection runtime imports"
  .venv/bin/python -c \
    "import av, grpc, httpx, PIL, torch, ultralytics; import cmvr.api.camera_service_pb2_grpc; print(f'torch={torch.__version__} cuda={torch.cuda.is_available()} ultralytics={ultralytics.__version__} pillow={PIL.__version__}')"
  echo "==> validating the PPE detection pipeline"
  .venv/bin/cmvr-edge-ai validate \
    --config configs/edge_ai.yaml \
    --pipeline detection
  .venv/bin/cmvr-edge-ai models
fi

if [[ "${profile}" == dev ]]; then
  echo "==> running tests"
  .venv/bin/pytest
fi

echo "==> bootstrap complete"
echo "run commands with: uv run --no-sync cmvr-edge-ai ..."
