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

# VigilCare Records — End-to-End Verification Script
# Tests the full digitization workflow: upload → entry → verify → approve → promote
#
# Prerequisites:
#   - API running on http://localhost:5217
#   - docker compose up -d (PostgreSQL, Redis, MinIO, Seq)
#   - Seed data applied (dotnet run applies seed on startup)
#   - A test PDF file at ./scripts/test-scan.pdf (create with: echo "test" | enscript -o - | ps2pdf - scripts/test-scan.pdf)
#
# Usage:
#   chmod +x scripts/run-vigilcare-records-verification.sh
#   ./scripts/run-vigilcare-records-verification.sh

API="http://localhost:5217/api/v1"
PASS=0
FAIL=0
TEST_FILE="${1:-scripts/test-scan.pdf}"

# Colors for terminal output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

log_pass() { PASS=$((PASS + 1)); echo -e "${GREEN}  PASS${NC} $1"; }
log_fail() { FAIL=$((FAIL + 1)); echo -e "${RED}  FAIL${NC} $1"; }
log_step() { echo -e "\n${YELLOW}── $1 ──${NC}"; }

# Create a minimal test PDF if it doesn't exist
if [ ! -f "$TEST_FILE" ]; then
    echo "Creating test PDF at $TEST_FILE..."
    mkdir -p "$(dirname "$TEST_FILE")"
    echo "%PDF-1.0
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<<>>>>endobj
xref
0 4
0000000000 65535 f 
0000000009 00000 n 
0000000058 00000 n 
0000000115 00000 n 
trailer<</Size 4/Root 1 0 R>>
startxref
206
%%EOF" > "$TEST_FILE"
fi

# ============================================================================
# Phase 1: Authentication
# ============================================================================
log_step "1. Authentication"

# Login as intake clerk
INTAKE_LOGIN=$(curl -s -X POST "$API/auth/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"intake1","password":"password"}')
INTAKE_TOKEN=$(echo "$INTAKE_LOGIN" | jq -r '.data.token')
INTAKE_REFRESH=$(echo "$INTAKE_LOGIN" | jq -r '.data.refreshToken')

if [ "$INTAKE_TOKEN" != "null" ] && [ -n "$INTAKE_TOKEN" ]; then
    log_pass "Intake clerk login returned JWT"
else
    log_fail "Intake clerk login failed"
    exit 1
fi

if [ "$INTAKE_REFRESH" != "null" ] && [ -n "$INTAKE_REFRESH" ]; then
    log_pass "Intake clerk login returned refresh token"
else
    log_fail "Intake clerk login missing refresh token"
fi

# Login as entry clerk
ENTRY_TOKEN=$(curl -s -X POST "$API/auth/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"entry1","password":"password"}' | jq -r '.data.token')

if [ "$ENTRY_TOKEN" != "null" ] && [ -n "$ENTRY_TOKEN" ]; then
    log_pass "Entry clerk login returned JWT"
else
    log_fail "Entry clerk login failed"
fi

# Login as verifier (must be different from entry clerk for separation of duties)
VERIFIER_TOKEN=$(curl -s -X POST "$API/auth/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"verifier1","password":"password"}' | jq -r '.data.token')

if [ "$VERIFIER_TOKEN" != "null" ] && [ -n "$VERIFIER_TOKEN" ]; then
    log_pass "Verifier login returned JWT"
else
    log_fail "Verifier login failed"
fi

# Login as approver
APPROVER_TOKEN=$(curl -s -X POST "$API/auth/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"approver1","password":"password"}' | jq -r '.data.token')

if [ "$APPROVER_TOKEN" != "null" ] && [ -n "$APPROVER_TOKEN" ]; then
    log_pass "Approver login returned JWT"
else
    log_fail "Approver login failed"
fi

# Verify /me endpoint
ME_ROLE=$(curl -s "$API/auth/me" \
    -H "Authorization: Bearer $INTAKE_TOKEN" | jq -r '.data.role')

if [ "$ME_ROLE" = "INTAKE_CLERK" ]; then
    log_pass "/me returns correct role: INTAKE_CLERK"
else
    log_fail "/me returned unexpected role: $ME_ROLE"
fi

# Verify 401 without token
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$API/auth/me")
if [ "$HTTP_CODE" = "401" ]; then
    log_pass "Unauthenticated /me returns 401"
else
    log_fail "Unauthenticated /me returned $HTTP_CODE (expected 401)"
fi

# Refresh token rotation
REFRESH_RESPONSE=$(curl -s -X POST "$API/auth/refresh" \
    -H "Content-Type: application/json" \
    -d "{\"refreshToken\":\"$INTAKE_REFRESH\"}")
NEW_TOKEN=$(echo "$REFRESH_RESPONSE" | jq -r '.data.token')
NEW_REFRESH=$(echo "$REFRESH_RESPONSE" | jq -r '.data.refreshToken')

if [ "$NEW_TOKEN" != "null" ] && [ -n "$NEW_TOKEN" ] && [ "$NEW_REFRESH" != "$INTAKE_REFRESH" ]; then
    log_pass "Refresh rotated tokens successfully"
    INTAKE_TOKEN="$NEW_TOKEN"
    INTAKE_REFRESH="$NEW_REFRESH"
else
    log_fail "Token refresh failed: $REFRESH_RESPONSE"
fi

# Logout revokes refresh token
LOGOUT_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/auth/logout" \
    -H "Content-Type: application/json" \
    -d "{\"refreshToken\":\"$INTAKE_REFRESH\"}")
if [ "$LOGOUT_CODE" = "204" ]; then
    log_pass "Logout revoked refresh token (204)"
else
    log_fail "Logout returned $LOGOUT_CODE (expected 204)"
fi

# Re-login for subsequent test phases
INTAKE_LOGIN=$(curl -s -X POST "$API/auth/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"intake1","password":"password"}')
INTAKE_TOKEN=$(echo "$INTAKE_LOGIN" | jq -r '.data.token')

# ============================================================================
# Phase 2: Upload and Batch Creation
# ============================================================================
log_step "2. Upload and Batch Creation"

UPLOAD_RESPONSE=$(curl -s -X POST "$API/digitization-batches" \
    -H "Authorization: Bearer $INTAKE_TOKEN" \
    -F "file=@$TEST_FILE" \
    -F "batchType=VITALS_SHEET" \
    -F "track=BACKFILL")

BATCH_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.data.id')
BATCH_STATUS=$(echo "$UPLOAD_RESPONSE" | jq -r '.data.status')

if [ "$BATCH_ID" != "null" ] && [ -n "$BATCH_ID" ]; then
    log_pass "Batch created: $BATCH_ID"
else
    log_fail "Batch creation failed: $UPLOAD_RESPONSE"
    exit 1
fi

if [ "$BATCH_STATUS" = "UPLOADED" ]; then
    log_pass "Initial status is UPLOADED"
else
    log_fail "Initial status is $BATCH_STATUS (expected UPLOADED)"
fi

# Verify presigned URL
DOC_URL=$(curl -s "$API/digitization-batches/$BATCH_ID" \
    -H "Authorization: Bearer $INTAKE_TOKEN" | jq -r '.data.documentUrl')

if [ "$DOC_URL" != "null" ] && [ -n "$DOC_URL" ]; then
    log_pass "Presigned URL returned for document"
else
    log_fail "No presigned URL returned"
fi

# ============================================================================
# Phase 3: Assign and Begin Entry
# ============================================================================
log_step "3. Assign and Begin Entry"

# Get entry clerk user ID
ENTRY_USER_ID=$(curl -s "$API/auth/me" \
    -H "Authorization: Bearer $ENTRY_TOKEN" | jq -r '.data.id')

# Assign batch to entry clerk
ASSIGN_RESPONSE=$(curl -s -X PATCH "$API/digitization-batches/$BATCH_ID/assign" \
    -H "Authorization: Bearer $INTAKE_TOKEN" \
    -H "Content-Type: application/json" \
    -d "{\"entryClerkUserId\":\"$ENTRY_USER_ID\"}")

ASSIGN_SUCCESS=$(echo "$ASSIGN_RESPONSE" | jq -r '.success')
if [ "$ASSIGN_SUCCESS" = "true" ]; then
    log_pass "Batch assigned to entry clerk"
else
    log_fail "Batch assignment failed: $(echo "$ASSIGN_RESPONSE" | jq -r '.error.message')"
fi

# ============================================================================
# Phase 4: Draft Data Entry
# ============================================================================
log_step "4. Draft Data Entry"

# Save draft patient
PATIENT_RESPONSE=$(curl -s -X PUT "$API/digitization-batches/$BATCH_ID/draft/patient" \
    -H "Authorization: Bearer $ENTRY_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
        "fullName": "E2E Test Patient",
        "dateOfBirth": "1985-06-15",
        "sex": "male",
        "bloodType": "A+",
        "emergencyContact": "Test Contact - 555-9999",
        "noKnownAllergies": true
    }')

if [ "$(echo "$PATIENT_RESPONSE" | jq -r '.success')" = "true" ]; then
    log_pass "Draft patient saved"
else
    log_fail "Draft patient save failed: $(echo "$PATIENT_RESPONSE" | jq -r '.error.message')"
fi

# Save draft encounter
ENCOUNTER_RESPONSE=$(curl -s -X PUT "$API/digitization-batches/$BATCH_ID/draft/encounter" \
    -H "Authorization: Bearer $ENTRY_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
        "admissionDate": "2026-06-20T08:00:00Z",
        "department": "Emergency Department",
        "roomBed": "ED-12",
        "admissionReason": "Chest pain, rule out MI"
    }')

if [ "$(echo "$ENCOUNTER_RESPONSE" | jq -r '.success')" = "true" ]; then
    log_pass "Draft encounter saved"
else
    log_fail "Draft encounter save failed"
fi

# Add observations
for OBS in \
    '{"observationCode":"HEART_RATE","value":95,"unit":"bpm","recordedAt":"2026-06-20T08:15:00Z"}' \
    '{"observationCode":"TEMP_C","value":37.1,"unit":"C","recordedAt":"2026-06-20T08:15:00Z"}' \
    '{"observationCode":"BP_SYSTOLIC","value":142,"unit":"mmHg","recordedAt":"2026-06-20T08:15:00Z"}' \
    '{"observationCode":"BP_DIASTOLIC","value":88,"unit":"mmHg","recordedAt":"2026-06-20T08:15:00Z"}' \
    '{"observationCode":"RESP_RATE","value":20,"unit":"breaths/min","recordedAt":"2026-06-20T08:15:00Z"}' \
    '{"observationCode":"SPO2","value":97,"unit":"%","recordedAt":"2026-06-20T08:15:00Z"}'
do
    OBS_RESULT=$(curl -s -X POST "$API/digitization-batches/$BATCH_ID/draft/observations" \
        -H "Authorization: Bearer $ENTRY_TOKEN" \
        -H "Content-Type: application/json" \
        -d "$OBS")
    OBS_CODE=$(echo "$OBS" | jq -r '.observationCode')
    if [ "$(echo "$OBS_RESULT" | jq -r '.success')" = "true" ]; then
        log_pass "Observation $OBS_CODE added"
    else
        log_fail "Observation $OBS_CODE failed: $(echo "$OBS_RESULT" | jq -r '.error.message')"
    fi
done

# Verify draft is complete
DRAFT_RESPONSE=$(curl -s "$API/digitization-batches/$BATCH_ID/draft" \
    -H "Authorization: Bearer $ENTRY_TOKEN")

OBS_COUNT=$(echo "$DRAFT_RESPONSE" | jq -r '.data.observations | length')
if [ "$OBS_COUNT" = "6" ]; then
    log_pass "Draft has 6 observations"
else
    log_fail "Draft has $OBS_COUNT observations (expected 6)"
fi

# Submit for verification
SUBMIT_RESPONSE=$(curl -s -X POST "$API/digitization-batches/$BATCH_ID/submit-for-verification" \
    -H "Authorization: Bearer $ENTRY_TOKEN")

if [ "$(echo "$SUBMIT_RESPONSE" | jq -r '.success')" = "true" ]; then
    log_pass "Submitted for verification"
else
    log_fail "Submit failed: $(echo "$SUBMIT_RESPONSE" | jq -r '.error.message')"
fi

# Verify status is now PENDING_VERIFICATION
CURRENT_STATUS=$(curl -s "$API/digitization-batches/$BATCH_ID" \
    -H "Authorization: Bearer $ENTRY_TOKEN" | jq -r '.data.batch.status')

if [ "$CURRENT_STATUS" = "PENDING_VERIFICATION" ]; then
    log_pass "Status is PENDING_VERIFICATION"
else
    log_fail "Status is $CURRENT_STATUS (expected PENDING_VERIFICATION)"
fi

# ============================================================================
# Phase 5: Separation of Duties Check
# ============================================================================
log_step "5. Separation of Duties"

# Entry clerk tries to verify their own batch — should get 409
SOD_RESPONSE=$(curl -s -X POST "$API/digitization-batches/$BATCH_ID/verify" \
    -H "Authorization: Bearer $ENTRY_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"fieldChecks":[],"passed":true}')

SOD_CODE=$(echo "$SOD_RESPONSE" | jq -r '.error.code')
if [ "$SOD_CODE" = "SEPARATION_OF_DUTIES_VIOLATION" ]; then
    log_pass "Entry clerk cannot verify own batch (409 SEPARATION_OF_DUTIES_VIOLATION)"
else
    log_fail "Separation of duties not enforced: $SOD_CODE"
fi

# ============================================================================
# Phase 6: Verification
# ============================================================================
log_step "6. Verification (by different user)"

VERIFY_RESPONSE=$(curl -s -X POST "$API/digitization-batches/$BATCH_ID/verify" \
    -H "Authorization: Bearer $VERIFIER_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
        "fieldChecks": [
            {"fieldPath": "patient.fullName", "passed": true},
            {"fieldPath": "patient.dateOfBirth", "passed": true},
            {"fieldPath": "observations[0].value", "passed": true},
            {"fieldPath": "observations[1].value", "passed": true},
            {"fieldPath": "observations[2].value", "passed": true},
            {"fieldPath": "observations[3].value", "passed": true},
            {"fieldPath": "observations[4].value", "passed": true},
            {"fieldPath": "observations[5].value", "passed": true}
        ],
        "passed": true
    }')

if [ "$(echo "$VERIFY_RESPONSE" | jq -r '.success')" = "true" ]; then
    log_pass "Verification passed"
else
    log_fail "Verification failed: $(echo "$VERIFY_RESPONSE" | jq -r '.error.message')"
fi

# Check status
VERIFIED_STATUS=$(curl -s "$API/digitization-batches/$BATCH_ID" \
    -H "Authorization: Bearer $VERIFIER_TOKEN" | jq -r '.data.batch.status')

if [ "$VERIFIED_STATUS" = "VERIFIED" ] || [ "$VERIFIED_STATUS" = "AWAITING_CLINICAL_APPROVAL" ]; then
    log_pass "Status after verification: $VERIFIED_STATUS"
else
    log_fail "Status after verification: $VERIFIED_STATUS (expected VERIFIED or AWAITING_CLINICAL_APPROVAL)"
fi

# ============================================================================
# Phase 7: Approval and Promotion
# ============================================================================
log_step "7. Approval and Promotion"

APPROVE_RESPONSE=$(curl -s -X POST "$API/digitization-batches/$BATCH_ID/approve" \
    -H "Authorization: Bearer $APPROVER_TOKEN" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: e2e-test-$(date +%s)")

if [ "$(echo "$APPROVE_RESPONSE" | jq -r '.success')" = "true" ]; then
    log_pass "Batch approved and promoted"
else
    log_fail "Approval failed: $(echo "$APPROVE_RESPONSE" | jq -r '.error.message')"
fi

# Verify final status is PROMOTED
FINAL_STATUS=$(curl -s "$API/digitization-batches/$BATCH_ID" \
    -H "Authorization: Bearer $APPROVER_TOKEN" | jq -r '.data.batch.status')

if [ "$FINAL_STATUS" = "PROMOTED" ]; then
    log_pass "Final status is PROMOTED"
else
    log_fail "Final status is $FINAL_STATUS (expected PROMOTED)"
fi

# Verify promotedAt is set
PROMOTED_AT=$(curl -s "$API/digitization-batches/$BATCH_ID" \
    -H "Authorization: Bearer $APPROVER_TOKEN" | jq -r '.data.batch.promotedAt')

if [ "$PROMOTED_AT" != "null" ] && [ -n "$PROMOTED_AT" ]; then
    log_pass "promotedAt timestamp set: $PROMOTED_AT"
else
    log_fail "promotedAt is null"
fi

# ============================================================================
# Phase 8: Illegal Transition Check
# ============================================================================
log_step "8. Illegal Transitions"

# Try to re-approve a promoted batch — should get 409
ILLEGAL_RESPONSE=$(curl -s -X POST "$API/digitization-batches/$BATCH_ID/approve" \
    -H "Authorization: Bearer $APPROVER_TOKEN" \
    -H "Content-Type: application/json")

ILLEGAL_CODE=$(echo "$ILLEGAL_RESPONSE" | jq -r '.error.code')
if [ "$ILLEGAL_CODE" = "ILLEGAL_STATUS_TRANSITION" ]; then
    log_pass "Cannot approve promoted batch (409 ILLEGAL_STATUS_TRANSITION)"
else
    log_fail "Illegal transition not blocked: $ILLEGAL_CODE"
fi

# ============================================================================
# Phase 9: Work Queue Overview
# ============================================================================
log_step "9. Work Queue Overview"

OVERVIEW_RESPONSE=$(curl -s "$API/work-queue/overview" \
    -H "Authorization: Bearer $APPROVER_TOKEN")

OVERVIEW_SUCCESS=$(echo "$OVERVIEW_RESPONSE" | jq -r '.success')
if [ "$OVERVIEW_SUCCESS" = "true" ]; then
    log_pass "Work queue overview returned successfully"
    echo "  Status counts: $(echo "$OVERVIEW_RESPONSE" | jq -c '.data.statusCounts')"
    echo "  Reject rate: $(echo "$OVERVIEW_RESPONSE" | jq -r '.data.rejectRate')"
else
    log_fail "Work queue overview failed"
fi

# ============================================================================
# Phase 10: Metrics Endpoint
# ============================================================================
log_step "10. Prometheus Metrics"

METRICS=$(curl -s http://localhost:5217/metrics)

if echo "$METRICS" | grep -q "digitization_batches_by_status"; then
    log_pass "digitization_batches_by_status metric present"
else
    log_fail "digitization_batches_by_status metric missing"
fi

if echo "$METRICS" | grep -q "digitization_promotion_duration_seconds"; then
    log_pass "digitization_promotion_duration_seconds metric present"
else
    log_fail "digitization_promotion_duration_seconds metric missing"
fi

if echo "$METRICS" | grep -q "digitization_rejection_total"; then
    log_pass "digitization_rejection_total metric present"
else
    log_fail "digitization_rejection_total metric missing"
fi

# ============================================================================
# Summary
# ============================================================================
echo ""
echo "============================================"
echo "  E2E Verification Complete"
echo "============================================"
echo -e "  ${GREEN}Passed: $PASS${NC}"
echo -e "  ${RED}Failed: $FAIL${NC}"
echo ""

if [ "$FAIL" -eq 0 ]; then
    echo -e "  ${GREEN}ALL TESTS PASSED${NC}"
    exit 0
else
    echo -e "  ${RED}$FAIL TEST(S) FAILED${NC}"
    exit 1
fi