#!/usr/bin/env bash

set -euo pipefail

SOURCE_PATH="${BASH_SOURCE[0]}"
while [[ -L "$SOURCE_PATH" ]]; do
  SOURCE_DIR="$(cd -P "$(dirname "$SOURCE_PATH")" && pwd)"
  SOURCE_PATH="$(readlink "$SOURCE_PATH")"
  [[ "$SOURCE_PATH" != /* ]] && SOURCE_PATH="$SOURCE_DIR/$SOURCE_PATH"
done

SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE_PATH")" && pwd)"
WORKSPACE_ROOT="$(cd -P "$SCRIPT_DIR/.." && pwd)"
PROJECT_ID="okstra-validation"
PROJECT_ROOT="${OKSTRA_VALIDATION_PROJECT_ROOT:-/tmp/okstra-validate.workflow}"
export OKSTRA_HOME="${OKSTRA_HOME:-$PROJECT_ROOT/.okstra-home}"

WORKSPACE_APP_PATH="$PROJECT_ROOT"
OKSTRA_SCRIPT="$WORKSPACE_ROOT/scripts/okstra.sh"
RUN_VALIDATOR_PATH="$WORKSPACE_ROOT/validators/validate-run.py"
SOURCE_ASSET_ROOT="$WORKSPACE_ROOT/agents"
# Arbitrary sample task-type used only to exercise the bundle-prep /
# discovery-pointer / task-catalog / asset-seeding machinery via render-only
# run_okstra. Must NOT require --approved-plan (excludes implementation and
# final-verification) and must have a tests/fixtures/final-report-data/
# <task-type>-001.data.json sample (used by prepare_run_validator_fixture).
TASK_TYPE="requirements-discovery"
PRIMARY_TASK_GROUP="validation"
PRIMARY_TASK_ID="asset-refresh-and-reference-expectations"
PRIMARY_BRIEF_FILENAME="validation-brief-primary.md"
SECONDARY_TASK_GROUP="discovery"
SECONDARY_TASK_ID="task-catalog"
SECONDARY_BRIEF_FILENAME="validation-brief-secondary.md"

# Workflow validation is a hermetic contract test for bundle prep / discovery
# artifacts / validator round-trips. It must not depend on the developer or CI
# machine having a preinstalled ~/.okstra runtime, and it must not reconcile or
# backfill against unrelated local state.
export OKSTRA_SKIP_INSTALL_CHECK="${OKSTRA_SKIP_INSTALL_CHECK:-1}"
export OKSTRA_CTL_SKIP_RECONCILE="${OKSTRA_CTL_SKIP_RECONCILE:-1}"
export OKSTRA_CTL_SKIP_BACKFILL="${OKSTRA_CTL_SKIP_BACKFILL:-1}"
# Same reason as the three above: the synthetic run must render the same way on
# every machine. cmux outranks tmux when present, so a maintainer running this
# from inside cmux would otherwise get the cmux adapter and a lead-session
# requirement this fixture never simulates. The cmux path has its own coverage
# in tests/run/test_cmux*.py and tests/contract/test_validate_session_conformance.py.
export CMUX_WORKSPACE_ID=""

# shellcheck source=lib/common.sh
source "$SCRIPT_DIR/lib/common.sh"
# shellcheck source=lib/paths.sh
source "$SCRIPT_DIR/lib/paths.sh"
LATEST_TASK_RELATIVE_PATH="$OKSTRA_DIR/discovery/latest-task.json"
TASK_CATALOG_RELATIVE_PATH="$OKSTRA_DIR/discovery/task-catalog.json"
# shellcheck source=lib/fixtures.sh
source "$SCRIPT_DIR/lib/fixtures.sh"
# shellcheck source=lib/runners.sh
source "$SCRIPT_DIR/lib/runners.sh"
# shellcheck source=lib/validate-assets.sh
source "$SCRIPT_DIR/lib/validate-assets.sh"
# shellcheck source=lib/validate-prompt-metadata.sh
source "$SCRIPT_DIR/lib/validate-prompt-metadata.sh"
# shellcheck source=lib/validate-tasks.sh
source "$SCRIPT_DIR/lib/validate-tasks.sh"
# shellcheck source=lib/summary.sh
source "$SCRIPT_DIR/lib/summary.sh"

trap 'on_error "$LINENO"' ERR

require_file "$OKSTRA_SCRIPT"
require_file "$RUN_VALIDATOR_PATH"

validate_project_root_safety

PRIMARY_BRIEF_PATH="$PROJECT_ROOT/$PRIMARY_BRIEF_FILENAME"
SECONDARY_BRIEF_PATH="$PROJECT_ROOT/$SECONDARY_BRIEF_FILENAME"
DISCOVERY_FILE="$PROJECT_ROOT/$LATEST_TASK_RELATIVE_PATH"
CATALOG_FILE="$PROJECT_ROOT/$TASK_CATALOG_RELATIVE_PATH"
PRIMARY_TASK_KEY="$(task_key "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID")"
SECONDARY_TASK_KEY="$(task_key "$SECONDARY_TASK_GROUP" "$SECONDARY_TASK_ID")"
PRIMARY_REFERENCE_EXPECTATIONS_FILE="$(task_root "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID")/instruction-set/reference-expectations.md"
SECONDARY_REFERENCE_EXPECTATIONS_FILE="$(task_root "$SECONDARY_TASK_GROUP" "$SECONDARY_TASK_ID")/instruction-set/reference-expectations.md"

step "Resetting the validation root"
reset_validation_root
pass "Validation root reset: $PROJECT_ROOT"

step "Writing validation briefs for multiple tasks"
write_validation_brief \
  "$PRIMARY_BRIEF_PATH" \
  "Primary validation brief for reference expectations" \
  "$PRIMARY_TASK_GROUP" \
  "$PRIMARY_TASK_ID" \
  "verify the initial task bundle and discovery pointer"
write_validation_brief \
  "$SECONDARY_BRIEF_PATH" \
  "Secondary validation brief for discovery catalog" \
  "$SECONDARY_TASK_GROUP" \
  "$SECONDARY_TASK_ID" \
  "verify task catalog retention across multiple prepared tasks"
require_file "$PRIMARY_BRIEF_PATH"
require_file "$SECONDARY_BRIEF_PATH"
pass "Validation briefs created for primary and secondary tasks"

step "Running the initial render-only okstra validation for the primary task"
if ! run_okstra "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID" "$PRIMARY_BRIEF_FILENAME"; then
  fail "Initial okstra render-only validation for the primary task failed"
fi
pass "Primary task render-only validation completed"

step "Checking seeded assets and primary task discovery artifacts"
if ! validate_seeded_assets match; then
  fail "Seeded project-local okstra assets are missing or do not match the source files"
fi
if ! validate_reference_expectations "$PRIMARY_BRIEF_PATH" "$PRIMARY_REFERENCE_EXPECTATIONS_FILE" "$PRIMARY_TASK_KEY"; then
  fail "Primary reference-expectations.md does not preserve the expected brief content"
fi
if ! validate_task_artifacts "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID"; then
  fail "Primary task manifest or run manifest validation failed"
fi
if ! validate_worker_prompt_metadata "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID"; then
  fail "Primary worker prompt metadata validation failed"
fi
if ! validate_latest_task_pointer "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID"; then
  fail "latest-task.json did not point to the primary task after the first run"
fi
if ! validate_task_catalog "$PRIMARY_TASK_KEY" "$PRIMARY_TASK_KEY"; then
  fail "task-catalog.json did not preserve the expected primary task entry"
fi
pass "Primary task discovery artifacts are valid"

step "Preparing validator fixture artifacts for the primary task"
# Fixture needs to render Phase 7 step 1.5 sibling artifacts; pass the
# repo root so the heredoc can import okstra_ctl.report_views and load
# inline assets from templates/reports/.
export OKSTRA_WORKSPACE_ROOT_FOR_FIXTURE="$WORKSPACE_ROOT"
if ! prepare_run_validator_fixture "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID" codex; then
  fail "Failed to prepare validator fixture artifacts for the primary task"
fi
pass "Primary task validator fixture prepared with an intentionally missing Codex prompt history file"

step "Ensuring the run validator rejects attempted workers without prompt history"
if ! run_validator_expectation "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID" failed "Codex worker with status \`timeout\` is missing worker prompt history file"; then
  fail "Run validator did not reject the missing worker prompt history artifact"
fi
pass "Run validator rejected the missing worker prompt history artifact as expected"

step "Restoring the missing worker prompt history file and rerunning the validator"
if ! write_worker_prompt_history_fixture "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID" codex; then
  fail "Failed to write the missing worker prompt history fixture"
fi
if ! run_validator_expectation "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID" passed; then
  fail "Run validator did not pass after restoring the worker prompt history artifact"
fi
pass "Run validator passed after the missing worker prompt history artifact was restored"

step "Running a second render-only okstra validation for the secondary task"
if ! run_okstra "$SECONDARY_TASK_GROUP" "$SECONDARY_TASK_ID" "$SECONDARY_BRIEF_FILENAME"; then
  fail "Render-only validation for the secondary task failed"
fi
pass "Secondary task render-only validation completed"

step "Checking that latest-task.json moves while task-catalog.json retains both tasks"
if ! validate_reference_expectations "$SECONDARY_BRIEF_PATH" "$SECONDARY_REFERENCE_EXPECTATIONS_FILE" "$SECONDARY_TASK_KEY"; then
  fail "Secondary reference-expectations.md does not preserve the expected brief content"
fi
if ! validate_task_artifacts "$SECONDARY_TASK_GROUP" "$SECONDARY_TASK_ID"; then
  fail "Secondary task manifest or run manifest validation failed"
fi
if ! validate_worker_prompt_metadata "$SECONDARY_TASK_GROUP" "$SECONDARY_TASK_ID"; then
  fail "Secondary worker prompt metadata validation failed"
fi
if ! validate_latest_task_pointer "$SECONDARY_TASK_GROUP" "$SECONDARY_TASK_ID"; then
  fail "latest-task.json did not point to the secondary task after the second run"
fi
if ! validate_task_catalog "$SECONDARY_TASK_KEY" "$PRIMARY_TASK_KEY" "$SECONDARY_TASK_KEY"; then
  fail "task-catalog.json did not preserve both prepared tasks"
fi
pass "latest-task.json and task-catalog.json now reflect distinct primary and secondary tasks"

# Removed: the historical "rerun without refresh preserves project-local
# assets" and "rerun with refresh regenerates project-local assets" stanzas.
# Those tested a contract from when `okstra install` seeded per-project
# `.claude/` files; install now writes only to `$HOME/.claude` and
# `$HOME/.okstra`, so the project-local sentinel is no longer a meaningful
# contract. The `--refresh-assets` flag was removed entirely in a paired
# commit; users with old scripts should switch to `okstra install --refresh`.

print_summary
