#!/usr/bin/env bash

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly ROOT
readonly RESULTS="${ROOT}/results"
readonly IMAGE="serein-leg-02-php"
readonly LOCKER_REGISTRY="${ROOT}/variants/locker-registry/src"
readonly LOCKER_TABLE="${ROOT}/variants/locker-table/src"
readonly SAME_DAY_COMMON="${ROOT}/variants/same-day-common/src"
readonly SAME_DAY_REGISTRY="${ROOT}/variants/same-day-registry/src"
readonly SAME_DAY_TABLE="${ROOT}/variants/same-day-table/src"

if [[ "${RESULTS}" != "${ROOT}/results" ]]; then
  echo "refusing to clear an unexpected results directory" >&2
  exit 65
fi

cd "${ROOT}"

milliseconds() {
  perl -MTime::HiRes=time -e 'printf "%.0f\n", time * 1000'
}

capture() {
  local name="$1"
  local expectation="$2"
  shift 2

  local directory="${RESULTS}/${name}"
  local started
  local finished
  local exit_code

  mkdir -p "${directory}"
  printf '%q ' "$@" \
    | sed -E 's/[[:space:]]+$//' >"${directory}/command.txt"
  printf '\n' >>"${directory}/command.txt"

  started="$(milliseconds)"
  set +e
  "$@" >"${directory}/output.txt.tmp" 2>&1
  exit_code=$?
  set -e
  finished="$(milliseconds)"

  sed -E -e 's/[[:space:]]+$//' -e '${/^$/d;}' \
    "${directory}/output.txt.tmp" >"${directory}/output.txt"
  rm "${directory}/output.txt.tmp"

  {
    printf 'expectation=%s\n' "${expectation}"
    printf 'exit_code=%s\n' "${exit_code}"
    printf 'duration_ms=%s\n' "$((finished - started))"
  } >"${directory}/metadata.txt"

  if [[ "${expectation}" == "pass" && ${exit_code} -ne 0 ]]; then
    echo "FAILED: ${name} should have passed" >&2
    return 1
  fi

  if [[ "${expectation}" == "fail" && ${exit_code} -eq 0 ]]; then
    echo "FAILED: ${name} should have detected the counterfactual" >&2
    return 1
  fi

  printf '%-58s expected %s (exit %s)\n' \
    "${name}" "${expectation}" "${exit_code}"
}

mutation_case() {
  local name="$1"
  local suite="$2"
  local filter="$3"
  local temporary
  local source

  temporary="$(mktemp -d)"
  capture "mutations/${name}/generate" pass \
    php mutate.php "${name}" "${temporary}"
  source="$(php -r '
    $data = json_decode(file_get_contents($argv[1]), true, 512, JSON_THROW_ON_ERROR);
    echo $data["source"];
  ' "${RESULTS}/mutations/${name}/generate/output.txt")"
  capture "diffs/${name}" fail \
    diff -u \
      --label "${source} (clean)" \
      --label "${source} (${name})" \
      "${temporary}/original/${source}" \
      "${temporary}/src/${source}"
  capture "negative/${name}" fail \
    docker run --rm \
      --volume "${temporary}/src:/experiment/src:ro" \
      "${IMAGE}" \
      php vendor/bin/phpunit --testsuite="${suite}" --filter="${filter}"
  rm -rf "${temporary}"
}

same_day_registry() {
  docker run --rm \
    --volume "${SAME_DAY_COMMON}/CapacityGateway.php:/experiment/src/CapacityGateway.php:ro" \
    --volume "${SAME_DAY_COMMON}/CapacityProviderUnavailable.php:/experiment/src/CapacityProviderUnavailable.php:ro" \
    --volume "${SAME_DAY_COMMON}/DeliveryAvailabilityFailed.php:/experiment/src/DeliveryAvailabilityFailed.php:ro" \
    --volume "${SAME_DAY_REGISTRY}/SameDayDelivery.php:/experiment/src/SameDayDelivery.php:ro" \
    --volume "${SAME_DAY_REGISTRY}/RegistryServices.php:/experiment/src/RegistryServices.php:ro" \
    "${IMAGE}" \
    "$@"
}

same_day_table() {
  docker run --rm \
    --volume "${SAME_DAY_COMMON}/CapacityGateway.php:/experiment/src/CapacityGateway.php:ro" \
    --volume "${SAME_DAY_COMMON}/CapacityProviderUnavailable.php:/experiment/src/CapacityProviderUnavailable.php:ro" \
    --volume "${SAME_DAY_COMMON}/DeliveryAvailabilityFailed.php:/experiment/src/DeliveryAvailabilityFailed.php:ro" \
    --volume "${SAME_DAY_TABLE}/OptionRule.php:/experiment/src/OptionRule.php:ro" \
    --volume "${SAME_DAY_TABLE}/DeliveryRule.php:/experiment/src/DeliveryRule.php:ro" \
    --volume "${SAME_DAY_TABLE}/SameDayRule.php:/experiment/src/SameDayRule.php:ro" \
    --volume "${SAME_DAY_TABLE}/RuleDefinitions.php:/experiment/src/RuleDefinitions.php:ro" \
    --volume "${SAME_DAY_TABLE}/RuleTableDeliveryOptions.php:/experiment/src/RuleTableDeliveryOptions.php:ro" \
    "${IMAGE}" \
    "$@"
}

rm -rf \
  "${RESULTS}/environment" \
  "${RESULTS}/positive" \
  "${RESULTS}/changes" \
  "${RESULTS}/mutations" \
  "${RESULTS}/diffs" \
  "${RESULTS}/negative" \
  "${RESULTS}/analysis" \
  "${RESULTS}/sources" \
  "${RESULTS}/provenance" \
  "${RESULTS}/verification" \
  "${RESULTS}/setup"
mkdir -p "${RESULTS}"

capture setup/build pass docker build --tag "${IMAGE}" .
capture environment/php pass docker run --rm "${IMAGE}" php --version
capture environment/packages pass docker run --rm "${IMAGE}" php bin/versions.php
capture environment/composer-audit pass \
  docker run --rm "${IMAGE}" composer audit --locked --no-interaction
capture positive/baseline-contract pass \
  docker run --rm "${IMAGE}" php vendor/bin/phpunit --testsuite=BaselineContract
capture positive/parity pass \
  docker run --rm "${IMAGE}" php vendor/bin/phpunit --testsuite=Parity
capture positive/identity pass \
  docker run --rm "${IMAGE}" php vendor/bin/phpunit --testsuite=Identity

capture changes/locker-registry/contract pass \
  docker run --rm \
    --volume "${LOCKER_REGISTRY}/LockerDelivery.php:/experiment/src/LockerDelivery.php:ro" \
    --volume "${LOCKER_REGISTRY}/RegistryServices.php:/experiment/src/RegistryServices.php:ro" \
    "${IMAGE}" \
    php vendor/bin/phpunit --testsuite=Locker --filter=Registry
capture changes/locker-table/contract pass \
  docker run --rm \
    --volume "${LOCKER_TABLE}/RuleDefinitions.php:/experiment/src/RuleDefinitions.php:ro" \
    "${IMAGE}" \
    php vendor/bin/phpunit --testsuite=Locker --filter=Table
capture changes/locker-registry/matrix pass \
  docker run --rm \
    --volume "${LOCKER_REGISTRY}/LockerDelivery.php:/experiment/src/LockerDelivery.php:ro" \
    --volume "${LOCKER_REGISTRY}/RegistryServices.php:/experiment/src/RegistryServices.php:ro" \
    "${IMAGE}" \
    php bin/locker-matrix.php registry
capture changes/locker-table/matrix pass \
  docker run --rm \
    --volume "${LOCKER_TABLE}/RuleDefinitions.php:/experiment/src/RuleDefinitions.php:ro" \
    "${IMAGE}" \
    php bin/locker-matrix.php table
capture changes/locker-parity pass \
  cmp \
    "${RESULTS}/changes/locker-registry/matrix/output.txt" \
    "${RESULTS}/changes/locker-table/matrix/output.txt"

capture changes/same-day-registry/contract pass \
  same_day_registry \
  php vendor/bin/phpunit --testsuite=SameDay --filter=Registry
capture changes/same-day-table/contract pass \
  same_day_table \
  php vendor/bin/phpunit --testsuite=SameDay --filter=Table
capture changes/same-day-registry/matrix pass \
  same_day_registry php bin/same-day-matrix.php registry
capture changes/same-day-table/matrix pass \
  same_day_table php bin/same-day-matrix.php table
capture changes/same-day-parity pass \
  cmp \
    "${RESULTS}/changes/same-day-registry/matrix/output.txt" \
    "${RESULTS}/changes/same-day-table/matrix/output.txt"

for mutation in \
  locker-registry-exclusive-maximum \
  locker-registry-remote-leak \
  locker-registry-wrong-order \
  locker-registry-missing-activation
do
  mutation_case "${mutation}" Locker Registry
done

for mutation in \
  locker-table-exclusive-maximum \
  locker-table-remote-leak \
  locker-table-wrong-order \
  locker-table-wrong-price
do
  mutation_case "${mutation}" Locker Table
done

for mutation in \
  same-day-registry-inclusive-noon \
  same-day-registry-call-before-guard \
  same-day-registry-swallow-provider-failure \
  same-day-registry-no-capacity-is-failure \
  same-day-registry-missing-activation
do
  mutation_case "${mutation}" SameDay Registry
done

for mutation in \
  same-day-table-inclusive-noon \
  same-day-table-call-before-guard \
  same-day-table-swallow-provider-failure \
  same-day-table-no-capacity-is-failure \
  same-day-table-missing-activation
do
  mutation_case "${mutation}" SameDay Table
done

capture analysis/change-surfaces pass \
  docker run --rm "${IMAGE}" php analyze.php
capture sources/primary pass \
  docker run --rm "${IMAGE}" php source-evidence.php
capture provenance/manifest pass \
  docker run --rm "${IMAGE}" php source-manifest.php
capture verification/results pass \
  docker run --rm \
    --volume "${RESULTS}:/experiment/results" \
    "${IMAGE}" \
    php verify-results.php

echo "LEG-02 baseline evidence retained in ${RESULTS}"
