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

TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGE_ROOT="$(cd "$TEST_DIR/.." && pwd)"

find "$PACKAGE_ROOT/scripts" -type f -name '*.sh' -print0 |
  while IFS= read -r -d '' script; do
    bash -n "$script"
  done

find "$PACKAGE_ROOT/tools" -type f -name '*.py' -print0 |
  while IFS= read -r -d '' script; do
    python3 -m py_compile "$script"
  done

grep -q 'openEuler-24.03-LTS-x86_64-dvd.iso' "$PACKAGE_ROOT/manifests/artifacts.lock.csv"
grep -q '786b9683659512e71c978c34aea806a97ed6cacf04e1b0a22017a50eec582cbe' "$PACKAGE_ROOT/manifests/artifacts.lock.csv"
grep -q '9cdc130f859bfca6cbd138950128fda358b88fb1ebadad4f937ebc4560fe990b' "$PACKAGE_ROOT/manifests/artifacts.lock.csv"
grep -q 'd55fa5cc699198917ba2bdc827da632ad77f009ba2642d2750456a976dbe5989' "$PACKAGE_ROOT/manifests/artifacts.lock.csv"
grep -q 'eec599110f733afe5e0331a85d8feb354ec079b088bdca2dd81a587c5b50f8e4' "$PACKAGE_ROOT/manifests/artifacts.lock.csv"
grep -q '0bcb763fddafba410f35cbde226aa7f8514b9fb82eb05a0c85f6588d1c13f8db' "$PACKAGE_ROOT/manifests/artifacts.lock.csv"

python3 - "$PACKAGE_ROOT/manifests/artifacts.lock.csv" "$PACKAGE_ROOT/manifests/component-baseline.csv" <<'PY'
import csv
import sys

for name in sys.argv[1:]:
    with open(name, encoding="utf-8", newline="") as handle:
        rows = list(csv.reader(handle))
    expected = len(rows[0])
    invalid = [index + 1 for index, row in enumerate(rows) if len(row) != expected]
    if invalid:
        raise SystemExit(f"{name}: invalid CSV rows {invalid}")
PY

if rg -n --glob '!*.example' --glob '!README.md' \
  'LTAI[0-9A-Za-z]{12,}|AKIA[0-9A-Z]{16}|BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY' \
  "$PACKAGE_ROOT"; then
  echo "secret-like value found in package source" >&2
  exit 1
fi

TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
cp "$PACKAGE_ROOT/config/project.env.example" "$TMP/project.env"
sed -i.bak \
  -e 's/PROJECT_CODE=REQUIRED/PROJECT_CODE=demo/' \
  -e 's/PROJECT_NAME=REQUIRED/PROJECT_NAME=demo/' \
  -e 's/TARGET_HOST_REF=REQUIRED_NON_SECRET_HOST_REFERENCE/TARGET_HOST_REF=demo-host/' \
  -e 's/BUSINESS_ID=REQUIRED/BUSINESS_ID=demo/' \
  -e 's/STORE_DB_NAME=REQUIRED/STORE_DB_NAME=demo/' \
  -e 's/CONFIG_RESTAURANT_ID=REQUIRED_NUMERIC/CONFIG_RESTAURANT_ID=1/' \
  -e 's#STORE_ROOT=/workspace/wwwroot/REQUIRED_STORE/project#STORE_ROOT=/workspace/wwwroot/demo/project#' \
  -e 's#AI_API_ROOT=/workspace/wwwroot/REQUIRED_AI_API/project#AI_API_ROOT=/workspace/wwwroot/demo_ai/project#' \
  -e 's#AI_STORE_ROOT=/workspace/wwwroot/REQUIRED_STORE/project/public/store#AI_STORE_ROOT=/workspace/wwwroot/demo/project/public/store#' \
  -e 's/REQUIRED_VERSION/demo/g' \
  -e 's/=REQUIRED$/=demo/g' \
  -e 's/REQUIRED_UNIQUE/demo/g' \
  -e 's/REQUIRED_DOMAIN_OR_IP/demo.example.com/' \
  -e 's|REQUIRED_HTTPS_URL|https://demo.example.com|' \
  -e 's/REQUIRED_NON_ROOT_USER/demo_deploy/' \
  -e 's/ALLOW_EOL_RUNTIME=false/ALLOW_EOL_RUNTIME=true/' \
  "$TMP/project.env"
rm -f "$TMP/project.env.bak"

python3 "$PACKAGE_ROOT/tools/render_template.py" \
  --env "$TMP/project.env" \
  --template "$PACKAGE_ROOT/runtime/nginx/online-single.conf.template" \
  --output "$TMP/nginx.conf"
grep -q 'listen 80;' "$TMP/nginx.conf"
grep -q 'listen 127.0.0.1:81;' "$TMP/nginx.conf"
grep -q 'worker_connections 8192;' "$PACKAGE_ROOT/runtime/nginx/nginx.conf.tuned"
grep -q 'client_max_body_size 100m;' "$PACKAGE_ROOT/runtime/nginx/nginx.conf.tuned"

cp "$PACKAGE_ROOT/config/secrets.env.example" "$TMP/secrets.env"
sed -i.bak \
  -e 's/CHANGE_ME/demo-secret-value/g' \
  "$TMP/secrets.env"
rm -f "$TMP/secrets.env.bak"
chmod 600 "$TMP/secrets.env"

for script in configure-mysql.sh initialize-mysql-account.sh configure-redis.sh; do
  "$PACKAGE_ROOT/scripts/$script" \
    --project-env "$TMP/project.env" \
    --secrets-env "$TMP/secrets.env" |
    grep -q 'SHADOW_ONLY'
done
"$PACKAGE_ROOT/scripts/configure-php-required-functions.sh" \
  --project-env "$TMP/project.env" |
  grep -q 'SHADOW_ONLY'
"$PACKAGE_ROOT/scripts/configure-nginx.sh" \
  --project-env "$TMP/project.env" |
  grep -q 'SHADOW_ONLY'

python3 "$PACKAGE_ROOT/tools/render_cloud_sql.py" \
  --project-env "$TMP/project.env" \
  --secrets-env "$TMP/secrets.env" \
  --output "$TMP/cloud.sql"
if grep -q 'demo-secret-value' "$TMP/cloud.sql"; then
  echo "rendered SQL exposed a raw secret" >&2
  exit 1
fi
grep -q 'CONVERT(0x' "$TMP/cloud.sql"
grep -q '616c695f6d7174745f617574685f6d6f6465' "$TMP/cloud.sql"

python3 "$PACKAGE_ROOT/tools/render_mysql_init_sql.py" \
  --project-env "$TMP/project.env" \
  --secrets-env "$TMP/secrets.env" \
  --output "$TMP/mysql-init.sql"
if grep -q 'demo-secret-value' "$TMP/mysql-init.sql"; then
  echo "rendered MySQL SQL exposed a raw secret" >&2
  exit 1
fi
grep -q 'CREATE DATABASE IF NOT EXISTS `demo`' "$TMP/mysql-init.sql"
grep -q 'GRANT SELECT,INSERT,UPDATE,DELETE' "$TMP/mysql-init.sql"
cp "$TMP/project.env" "$TMP/project-remote-mysql.env"
sed -i.bak 's/MYSQL_APP_HOST=127.0.0.1/MYSQL_APP_HOST=%/' "$TMP/project-remote-mysql.env"
rm -f "$TMP/project-remote-mysql.env.bak"
if python3 "$PACKAGE_ROOT/tools/render_mysql_init_sql.py" \
  --project-env "$TMP/project-remote-mysql.env" \
  --secrets-env "$TMP/secrets.env" \
  --output "$TMP/mysql-remote.sql" >/dev/null 2>&1; then
  echo "remote MySQL application account was not rejected" >&2
  exit 1
fi

mkdir -p "$TMP/mysql-backup"
cp "$PACKAGE_ROOT/tests/fixtures/my.cnf" "$TMP/my.cnf"
python3 "$PACKAGE_ROOT/tools/configure_mysql.py" \
  --config "$TMP/my.cnf" \
  --snippet "$PACKAGE_ROOT/runtime/mysql/zhct-online-single.cnf" \
  --backup "$TMP/mysql-backup/my.cnf.before"
grep -q 'sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"' "$TMP/my.cnf"
if grep -q 'STRICT_TRANS_TABLES' "$TMP/my.cnf"; then
  echo "strict MySQL mode remained active" >&2
  exit 1
fi
test -f "$TMP/mysql-backup/my.cnf.before"

mkdir -p "$TMP/php-backup"
cp "$PACKAGE_ROOT/tests/fixtures/php.ini" "$TMP/php.ini"
python3 "$PACKAGE_ROOT/tools/update_php_disable_functions.py" \
  --php-ini "$TMP/php.ini" \
  --required-functions "exec,readlink,popen,proc_open,proc_get_status" \
  --backup "$TMP/php-backup/php.ini.before"
grep -q 'disable_functions = system,passthru' "$TMP/php.ini"
test -f "$TMP/php-backup/php.ini.before"
if python3 "$PACKAGE_ROOT/tools/update_php_disable_functions.py" \
  --php-ini "$PACKAGE_ROOT/tests/fixtures/php.ini" \
  --required-functions "exec,system" \
  --backup "$TMP/php-backup/rejected.before" >/dev/null 2>&1; then
  echo "unapproved PHP function was not rejected" >&2
  exit 1
fi

mkdir -p "$TMP/redis-backup"
cp "$PACKAGE_ROOT/tests/fixtures/redis.conf" "$TMP/redis.conf"
python3 "$PACKAGE_ROOT/tools/configure_redis.py" \
  --config "$TMP/redis.conf" \
  --project-env "$TMP/project.env" \
  --secrets-env "$TMP/secrets.env" \
  --backup "$TMP/redis-backup/redis.conf.before"
grep -q '^bind 127.0.0.1$' "$TMP/redis.conf"
grep -q '^protected-mode yes$' "$TMP/redis.conf"
grep -q '^appendonly yes$' "$TMP/redis.conf"
grep -q '^requirepass demo-secret-value$' "$TMP/redis.conf"
test -f "$TMP/redis-backup/redis.conf.before"
cp "$TMP/project.env" "$TMP/project-public-redis.env"
sed -i.bak 's/REDIS_BIND=127.0.0.1/REDIS_BIND=0.0.0.0/' "$TMP/project-public-redis.env"
rm -f "$TMP/project-public-redis.env.bak"
if python3 "$PACKAGE_ROOT/tools/configure_redis.py" \
  --config "$PACKAGE_ROOT/tests/fixtures/redis.conf" \
  --project-env "$TMP/project-public-redis.env" \
  --secrets-env "$TMP/secrets.env" \
  --backup "$TMP/redis-backup/rejected.before" >/dev/null 2>&1; then
  echo "public Redis bind was not rejected" >&2
  exit 1
fi

test ! -d "$PACKAGE_ROOT/runtime/supervisor"
test ! -d "$PACKAGE_ROOT/runtime/cron"

mkdir -p "$TMP/store/extend/mqtt" "$TMP/mqtt-backup"
cp "$PACKAGE_ROOT/tests/fixtures/MqttConfig.php" "$TMP/store/extend/mqtt/MqttConfig.php"
cp "$PACKAGE_ROOT/tests/fixtures/MQTTServer.php" "$TMP/store/extend/mqtt/MQTTServer.php"
python3 "$PACKAGE_ROOT/tools/configure_mqtt_auth.py" \
  --project-root "$TMP/store" \
  --backup-dir "$TMP/mqtt-backup"
grep -q "DeviceCredential" "$TMP/store/extend/mqtt/MqttConfig.php"
grep -q "DeviceCredential" "$TMP/store/extend/mqtt/MQTTServer.php"
grep -q "ali_mqtt_auth_mode" "$TMP/store/extend/mqtt/MqttConfig.php"
test -f "$TMP/mqtt-backup/MqttConfig.php.before-mqtt-auth"
test -f "$TMP/mqtt-backup/MQTTServer.php.before-mqtt-auth"

mkdir -p "$TMP/store/application" "$TMP/backup"
printf '%s\n' \
  '<?php' \
  '$config = [' \
  "    'baidu_apikey' => 'legacy-placeholder'," \
  "    'baidu_secretkey' => 'legacy-placeholder'," \
  '];' \
  > "$TMP/store/application/config.php"
python3 "$PACKAGE_ROOT/tools/configure_baidu_online.py" \
  --project-root "$TMP/store" \
  --secrets-env "$TMP/secrets.env" \
  --secret-file "$TMP/cloud-secrets.php" \
  --backup-dir "$TMP/backup"
grep -q 'zhctCloudSecrets' "$TMP/store/application/config.php"
if grep -q 'demo-secret-value' "$TMP/store/application/config.php"; then
  echo "Store config exposed a raw secret" >&2
  exit 1
fi
grep -q 'demo-secret-value' "$TMP/cloud-secrets.php"
test -f "$TMP/backup/config.php.before-baidu-online"

echo "PACKAGE_STATIC_TEST_PASS"
