#!/usr/bin/env bash

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly ROOT
readonly RESULTS="${ROOT}/results"
readonly IMAGE="serein-leg-01-php"

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 's/[[:space:]]+$//' \
    "${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 '%-52s expected %s (exit %s)\n' \
    "${name}" "${expectation}" "${exit_code}"
}

mutate_case() {
  local name="$1"
  local relative="$2"
  local expectation="$3"
  local suite="$4"
  local mutated="${RESULTS}/mutations/${name}/$(basename "${relative}")"

  capture "mutations/${name}/generate" pass \
    php mutate.php "${name}" "${mutated}"
  capture "diffs/${name}" fail \
    diff -u \
      --label "${relative} (clean)" \
      --label "${relative} (${name})" \
      "${ROOT}/${relative}" \
      "${mutated}"
  capture "${expectation}/${name}" fail \
    docker run --rm \
      --volume "${mutated}:/experiment/${relative}:ro" \
      "${IMAGE}" \
      php vendor/bin/phpunit --testsuite="${suite}"
}

rm -rf \
  "${RESULTS}/setup" \
  "${RESULTS}/environment" \
  "${RESULTS}/positive" \
  "${RESULTS}/mutations" \
  "${RESULTS}/diffs" \
  "${RESULTS}/negative" \
  "${RESULTS}/brittle" \
  "${RESULTS}/review" \
  "${RESULTS}/analysis" \
  "${RESULTS}/sources" \
  "${RESULTS}/provenance" \
  "${RESULTS}/verification"
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/observations pass \
  docker run --rm "${IMAGE}" php bin/observe.php
capture positive/characterization pass \
  docker run --rm "${IMAGE}" php vendor/bin/phpunit --testsuite=Characterization
capture positive/parity pass \
  docker run --rm "${IMAGE}" php vendor/bin/phpunit --testsuite=Parity
capture positive/recording pass \
  docker run --rm "${IMAGE}" php vendor/bin/phpunit --testsuite=Recording
capture positive/happy-path-only pass \
  docker run --rm "${IMAGE}" php vendor/bin/phpunit --testsuite=HappyPathOnly

mutate_case \
  exclusive-weight-edge \
  src/BasePrice.php \
  negative \
  Characterization
mutate_case \
  inclusive-insurance-threshold \
  src/InsurancePrice.php \
  negative \
  Characterization
mutate_case \
  round-insurance-down \
  src/InsurancePrice.php \
  negative \
  Characterization
mutate_case \
  omit-remote-surcharge \
  src/RemoteAreaSurcharge.php \
  negative \
  Characterization
mutate_case \
  discount-remote-surcharge \
  src/ExtractedPostageQuote.php \
  negative \
  Characterization
mutate_case \
  zero-quote-for-unsupported-destination \
  src/ExtractedPostageQuote.php \
  negative \
  Characterization
mutate_case \
  generic-unsupported-failure \
  src/ExtractedPostageQuote.php \
  negative \
  Characterization
mutate_case \
  reorder-diagnostic-trace \
  src/ExtractedPostageQuote.php \
  brittle \
  Recording
mutate_case \
  reorder-independent-calculations \
  src/ExtractedPostageQuote.php \
  brittle \
  Recording
mutate_case \
  refuse-zero-declared-value \
  src/ExtractedPostageQuote.php \
  review \
  Characterization

for harmless in \
  reorder-diagnostic-trace \
  reorder-independent-calculations
do
  mutated="${RESULTS}/mutations/${harmless}/ExtractedPostageQuote.php"
  capture "positive/${harmless}" pass \
    docker run --rm \
      --volume "${mutated}:/experiment/src/ExtractedPostageQuote.php:ro" \
      "${IMAGE}" \
      php vendor/bin/phpunit --testsuite=Characterization
done

for survivor in \
  inclusive-insurance-threshold \
  round-insurance-down
do
  mutated="${RESULTS}/mutations/${survivor}/InsurancePrice.php"
  capture "positive/happy-path-survives-${survivor}" pass \
    docker run --rm \
      --volume "${mutated}:/experiment/src/InsurancePrice.php:ro" \
      "${IMAGE}" \
      php vendor/bin/phpunit --testsuite=HappyPathOnly
done

capture analysis/inventory 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 "Characterization evidence retained in ${RESULTS}"
