#!/usr/bin/env bash
set -u -o pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
API_BASE="${API_BASE:-http://localhost:5202/api}"
DOC_PATH="$REPO_ROOT/docs/s06-acceptance-run.md"
ARTIFACT_DIR="$REPO_ROOT/docs/artifacts/s06-acceptance"
LOG_DIR="$ARTIFACT_DIR/logs"
AUTH_TOKEN="${AUTH_TOKEN:-}"
TEST_TARGET="${TEST_TARGET:-src/end-to-end-trust-loop.test.tsx}"
PRECHECK_TOKEN_FILE="$ARTIFACT_DIR/.dev-auth-token.txt"

mkdir -p "$LOG_DIR"

TIMESTAMP_UTC="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
RUN_ID="$(date -u +"%Y%m%dT%H%M%SZ")"

SEED_STATUS="not-run"
SEED_EXIT_CODE=""
SEED_DURATION_MS="0"
SEED_LOG="$LOG_DIR/${RUN_ID}-acceptance-data.log"
SEED_SUMMARY="Not run."

TEST_STATUS="not-run"
TEST_EXIT_CODE=""
TEST_DURATION_MS="0"
TEST_LOG="$LOG_DIR/${RUN_ID}-end-to-end-trust-loop.log"
TEST_SUMMARY="Not run."

PREFLIGHT_STATUS="not-run"
PREFLIGHT_EXIT_CODE=""
PREFLIGHT_DURATION_MS="0"
PREFLIGHT_LOG="$LOG_DIR/${RUN_ID}-preflight.log"
PREFLIGHT_SUMMARY="Not run."

RUN_AUTH_SOURCE="provided"
OVERALL_RESULT="pass"
HARD_FAIL=0

note() {
  printf '%s\n' "$*"
}

run_logged() {
  local key="$1"
  local log_file="$2"
  shift 2

  local start_ms end_ms exit_code status summary
  start_ms="$(python3 - <<'PY'
import time
print(int(time.time() * 1000))
PY
)"

  set +e
  "$@" >"$log_file" 2>&1
  exit_code=$?
  set -e

  end_ms="$(python3 - <<'PY'
import time
print(int(time.time() * 1000))
PY
)"

  if [[ "$exit_code" -eq 0 ]]; then
    status="pass"
    summary="Command passed."
  else
    status="fail"
    summary="Command failed with exit ${exit_code}."
  fi

  case "$key" in
    preflight)
      PREFLIGHT_STATUS="$status"
      PREFLIGHT_EXIT_CODE="$exit_code"
      PREFLIGHT_DURATION_MS="$((end_ms - start_ms))"
      PREFLIGHT_SUMMARY="$summary"
      ;;
    seed)
      SEED_STATUS="$status"
      SEED_EXIT_CODE="$exit_code"
      SEED_DURATION_MS="$((end_ms - start_ms))"
      SEED_SUMMARY="$summary"
      ;;
    test)
      TEST_STATUS="$status"
      TEST_EXIT_CODE="$exit_code"
      TEST_DURATION_MS="$((end_ms - start_ms))"
      TEST_SUMMARY="$summary"
      ;;
  esac

  return "$exit_code"
}

mint_local_dev_token() {
  python3 - "$REPO_ROOT" <<'PY'
import base64
import hashlib
import hmac
import json
import sqlite3
import sys
import time
from pathlib import Path

repo = Path(sys.argv[1])
api_base = repo / 'JobTrackerApi'
config_path = api_base / 'appsettings.Development.json'
db_path = api_base / 'jobtracker.db'

if not config_path.exists() or not db_path.exists():
    raise SystemExit(1)

cfg = json.loads(config_path.read_text(encoding='utf-8'))
auth = cfg.get('Auth') or {}
key = (auth.get('JwtKey') or '').strip()
issuer = (auth.get('JwtIssuer') or 'JobTrackerApi').strip()
audience = (auth.get('JwtAudience') or 'job-tracker-ui').strip()
if not key:
    raise SystemExit(1)

conn = sqlite3.connect(db_path)
cur = conn.cursor()
row = cur.execute(
    """
    SELECT u.Id, COALESCE(u.Email,''), COALESCE(u.UserName,''), COALESCE(r.Name,'')
    FROM AspNetUsers u
    LEFT JOIN AspNetUserRoles ur ON ur.UserId = u.Id
    LEFT JOIN AspNetRoles r ON r.Id = ur.RoleId
    WHERE LOWER(COALESCE(u.Email,'')) = 'admin@example.com'
    LIMIT 1
    """
).fetchone()
if not row:
    raise SystemExit(1)
user_id, email, username, role = row
now = int(time.time())
payload = {
    'iss': issuer,
    'aud': audience,
    'nbf': now - 5,
    'exp': now + 12 * 60 * 60,
    'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier': user_id,
}
if email:
    payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'] = email
if username:
    payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'] = username
if role:
    payload['http://schemas.microsoft.com/ws/2008/06/identity/claims/role'] = role

header = {'alg': 'HS256', 'typ': 'JWT'}

def b64url(data: bytes) -> str:
    return base64.urlsafe_b64encode(data).rstrip(b'=').decode('ascii')

segments = [
    b64url(json.dumps(header, separators=(',', ':')).encode('utf-8')),
    b64url(json.dumps(payload, separators=(',', ':')).encode('utf-8')),
]
signing_input = '.'.join(segments).encode('ascii')
signature = hmac.new(key.encode('utf-8'), signing_input, hashlib.sha256).digest()
segments.append(b64url(signature))
print('.'.join(segments))
PY
}

extract_browser_section() {
  python3 - "$DOC_PATH" <<'PY'
import sys
from pathlib import Path

path = Path(sys.argv[1])
start = '<!-- acceptance-run:browser:start -->'
end = '<!-- acceptance-run:browser:end -->'
placeholder = "- Pending guided browser run. Update this section with `/jobs`, workspace, `/reminders`, and `/dashboard` observations.\n- Record the manual-send boundary observation, Gmail continuity status, and screenshot/debug-bundle paths."

if not path.exists():
    print(placeholder)
    raise SystemExit(0)

text = path.read_text(encoding='utf-8')
if start not in text or end not in text:
    print(placeholder)
    raise SystemExit(0)

segment = text.split(start, 1)[1].split(end, 1)[0].strip('\n')
print(segment.strip() or placeholder)
PY
}

render_doc() {
  local browser_section generated_section
  browser_section="$(extract_browser_section)"

  generated_section=$(cat <<EOF
## Run Metadata

- Run id: "${RUN_ID}"
- Generated at (UTC): "${TIMESTAMP_UTC}"
- API base: "${API_BASE}"
- Auth token source: ${RUN_AUTH_SOURCE}
- Overall runner result: **${OVERALL_RESULT}**

## Shell Verification Summary

| Step | Status | Exit | Duration | Notes | Log |
|---|---|---:|---:|---|---|
| Preflight | ${PREFLIGHT_STATUS} | ${PREFLIGHT_EXIT_CODE:-n/a} | ${PREFLIGHT_DURATION_MS}ms | ${PREFLIGHT_SUMMARY} | "${PREFLIGHT_LOG#$REPO_ROOT/}" |
| Seed acceptance data | ${SEED_STATUS} | ${SEED_EXIT_CODE:-n/a} | ${SEED_DURATION_MS}ms | ${SEED_SUMMARY} | "${SEED_LOG#$REPO_ROOT/}" |
| UI trust-loop test | ${TEST_STATUS} | ${TEST_EXIT_CODE:-n/a} | ${TEST_DURATION_MS}ms | ${TEST_SUMMARY} | "${TEST_LOG#$REPO_ROOT/}" |

## Runner Observations

- Preflight is the only hard-stop gate. If the backend is unreachable, this runner exits non-zero after recording the failure.
- Seeding failures and UI regression failures are still written into this artifact so auth/test blockers are visible instead of disappearing behind a shell exit.
- Secrets are redacted by design: the runner never prints bearer tokens and only records the token source category.

## Auth / Blocker Guidance

- If the environment already exported "AUTH_TOKEN", the runner reuses it.
- If "AUTH_TOKEN" is missing and the API base is the default localhost dev target, the runner attempts a **local dev JWT fallback** using the checked-in dev JWT settings plus the local SQLite admin user so acceptance seeding can proceed without printing a token.
- If the fallback cannot mint or validate a token, treat the seed/browser run as **auth blocked**. In that case, log in via "POST /api/auth/login" with the real local account (or reuse an already-authenticated browser session), export only the access token, and rerun the runner.
- Gmail continuity may legitimately remain blocked when Gmail is not connected/configured for the local user; that is expected to be called out explicitly below instead of triggering auto-send behavior.
EOF
)

  cat >"$DOC_PATH" <<EOF
# S06 Acceptance Run

This document captures the live S06 acceptance rerun for the "/jobs → workspace → reminders/dashboard → follow-up/manual-send boundary" loop.

<!-- acceptance-run:generated:start -->
${generated_section}
<!-- acceptance-run:generated:end -->

## Guided Browser Observations

<!-- acceptance-run:browser:start -->
${browser_section}
<!-- acceptance-run:browser:end -->
EOF
}

set -e

if [[ -z "$AUTH_TOKEN" && "$API_BASE" == "http://localhost:5202/api" ]]; then
  if AUTH_TOKEN="$(mint_local_dev_token 2>/dev/null)" && [[ -n "$AUTH_TOKEN" ]]; then
    RUN_AUTH_SOURCE="minted-local-dev-admin"
    printf '%s' "$AUTH_TOKEN" > "$PRECHECK_TOKEN_FILE"
  else
    AUTH_TOKEN=""
    RUN_AUTH_SOURCE="missing-no-dev-fallback"
  fi
elif [[ -n "$AUTH_TOKEN" ]]; then
  RUN_AUTH_SOURCE="provided"
else
  RUN_AUTH_SOURCE="missing-nondefault-api"
fi

if run_logged preflight "$PREFLIGHT_LOG" env AUTH_TOKEN="$AUTH_TOKEN" bash "$SCRIPT_DIR/s06-preflight.sh"; then
  PREFLIGHT_SUMMARY="Backend reachable. Preflight passed or reached the expected auth-limited partial-pass state."
else
  PREFLIGHT_SUMMARY="Backend preflight failed. See log for the exact connection/auth error."
  OVERALL_RESULT="hard-fail"
  HARD_FAIL=1
  render_doc
  note "acceptance.result=${OVERALL_RESULT}"
  note "acceptance.doc=${DOC_PATH#$REPO_ROOT/}"
  exit 1
fi

if [[ -n "$AUTH_TOKEN" ]]; then
  if run_logged seed "$SEED_LOG" env AUTH_TOKEN="$AUTH_TOKEN" bash "$SCRIPT_DIR/s06-acceptance-data.sh"; then
    SEED_SUMMARY="Acceptance fixture seeded or updated successfully."
  else
    SEED_SUMMARY="Acceptance seed failed even with a token source available. Review the log for API or data-contract issues."
    OVERALL_RESULT="partial"
  fi
else
  if run_logged seed "$SEED_LOG" env -u AUTH_TOKEN bash "$SCRIPT_DIR/s06-acceptance-data.sh"; then
    SEED_SUMMARY="Unexpected success without AUTH_TOKEN. Review the environment assumptions."
  else
    SEED_SUMMARY="Acceptance seed is auth blocked because no bearer token was available and the local dev fallback was not usable."
    OVERALL_RESULT="partial"
  fi
fi

if run_logged test "$TEST_LOG" bash -lc "cd '$REPO_ROOT/job-tracker-ui' && CI=true npm test -- --runInBand --watch=false '$TEST_TARGET'"; then
  TEST_SUMMARY="Relevant trust-loop regression passed."
else
  TEST_SUMMARY="Relevant trust-loop regression failed. The artifact keeps the failure visible for follow-up."
  OVERALL_RESULT="partial"
fi

render_doc

note "acceptance.result=${OVERALL_RESULT}"
note "acceptance.doc=${DOC_PATH#$REPO_ROOT/}"
note "acceptance.preflight=${PREFLIGHT_STATUS}"
note "acceptance.seed=${SEED_STATUS}"
note "acceptance.test=${TEST_STATUS}"

exit 0
