#!/usr/bin/env bash
# Generate dependency/artifact security evidence and run available scanners.
set -euo pipefail

ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
REPORT_DIR="${ROOT_DIR}/target/supply-chain-gate"
SUMMARY_JSON="${REPORT_DIR}/summary.json"
SUMMARY_TXT="${REPORT_DIR}/summary.txt"
METRICS_FILE="${REPORT_DIR}/metrics.prom"
SBOM_JSON="${REPORT_DIR}/sbom.cargo-metadata.json"
TREE_TXT="${REPORT_DIR}/dependency-tree.txt"
SECRET_TXT="${REPORT_DIR}/secret-scan.txt"
PUSHGATEWAY_URL=${QUALITY_GATE_PUSHGATEWAY_URL:-}
PUSHGATEWAY_JOB=${LESAVKA_SUPPLY_CHAIN_PUSHGATEWAY_JOB:-platform-quality-ci}
ENFORCE_TOOLS=${LESAVKA_SUPPLY_CHAIN_ENFORCE_TOOLS:-0}

mkdir -p "${REPORT_DIR}"
cd "${ROOT_DIR}"

branch=${BRANCH_NAME:-${GIT_BRANCH:-}}
if [[ -z "${branch}" ]]; then
  branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)
fi
commit=${GIT_COMMIT:-}
if [[ -z "${commit}" ]]; then
  commit=$(git rev-parse --short HEAD 2>/dev/null || echo unknown)
fi

status=0
cargo metadata --locked --format-version 1 >"${SBOM_JSON}"
cargo tree --locked --workspace >"${TREE_TXT}"

secret_status=ok
: >"${SECRET_TXT}"
while IFS= read -r path; do
  case "$path" in
    Cargo.lock|target/*|dist/*) continue ;;
  esac
  [[ -f "$path" ]] || continue
  if file "$path" | grep -qi 'text\|json\|xml\|yaml\|toml\|script'; then
    if grep -EHni \
      -e 'AKIA[0-9A-Z]{16}' \
      -e '-----BEGIN (RSA|EC|OPENSSH|PRIVATE) KEY-----' \
      -e "(password|secret|token|api[_-]?key)[[:space:]]*[:=][[:space:]]*[\"'][A-Za-z0-9_+/=.-]{12,}[\"']" \
      "$path" >>"${SECRET_TXT}" 2>/dev/null; then
      secret_status=failed
      status=1
    fi
  fi
done < <(git ls-files)

audit_status=not_applicable
if command -v cargo-audit >/dev/null 2>&1; then
  audit_status=ok
  if ! cargo audit --locked >"${REPORT_DIR}/cargo-audit.txt" 2>&1; then
    audit_status=failed
    status=1
  fi
elif [[ "${ENFORCE_TOOLS}" == "1" ]]; then
  audit_status=failed
  status=1
fi

deny_status=not_applicable
if command -v cargo-deny >/dev/null 2>&1; then
  deny_status=ok
  if ! cargo deny check >"${REPORT_DIR}/cargo-deny.txt" 2>&1; then
    deny_status=failed
    status=1
  fi
elif [[ "${ENFORCE_TOOLS}" == "1" ]]; then
  deny_status=failed
  status=1
fi

artifact_status=not_applicable
if compgen -G "dist/*.tar.gz" >/dev/null; then
  artifact_status=ok
  sha256sum dist/*.tar.gz >"${REPORT_DIR}/SHA256SUMS"
fi

python3 - "${SUMMARY_JSON}" "${SUMMARY_TXT}" "${METRICS_FILE}" "${branch}" "${commit}" "${secret_status}" "${audit_status}" "${deny_status}" "${artifact_status}" <<'PY'
import json
import pathlib
import sys
from datetime import datetime, timezone

summary_path = pathlib.Path(sys.argv[1])
text_path = pathlib.Path(sys.argv[2])
metrics_path = pathlib.Path(sys.argv[3])
branch = sys.argv[4]
commit = sys.argv[5]
secret_status = sys.argv[6]
audit_status = sys.argv[7]
deny_status = sys.argv[8]
artifact_status = sys.argv[9]

def esc(value: str) -> str:
    return value.replace('\\', r'\\').replace('\n', r'\n').replace('"', r'\"')

checks = {
    'secret_scan': secret_status,
    'cargo_audit': audit_status,
    'cargo_deny': deny_status,
    'artifact_checksums': artifact_status,
    'sbom': 'ok',
}
status = 'failed' if any(value == 'failed' for value in checks.values()) else 'ok'
summary = {
    'suite': 'lesavka',
    'check': 'supply_chain',
    'status': status,
    'branch': branch,
    'commit': commit,
    'generated_at': datetime.now(timezone.utc).isoformat(),
    'checks': checks,
}
summary_path.write_text(json.dumps(summary, indent=2, sort_keys=True) + '\n', encoding='utf-8')
lines = ['supply chain gate report', f'status: {status}', f'branch: {branch}', f'commit: {commit}', '']
for name, value in checks.items():
    lines.append(f'{name}: {value}')
text_path.write_text('\n'.join(lines) + '\n', encoding='utf-8')
labels = f'suite="lesavka",branch="{esc(branch)}",commit="{esc(commit)}"'
metrics = [
    '# HELP platform_quality_gate_checks_total Check outcomes from the latest lesavka gate run.',
    '# TYPE platform_quality_gate_checks_total gauge',
]
for state in ('ok', 'failed', 'not_applicable'):
    value = 1 if state == status else 0
    metrics.append(f'platform_quality_gate_checks_total{{{labels},check="supply_chain",status="{state}"}} {value}')
metrics.append('# HELP lesavka_supply_chain_subcheck_info Supply-chain subcheck evidence status.')
metrics.append('# TYPE lesavka_supply_chain_subcheck_info gauge')
for name, value in checks.items():
    metrics.append(f'lesavka_supply_chain_subcheck_info{{{labels},subcheck="{esc(name)}",status="{esc(value)}"}} 1')
metrics_path.write_text('\n'.join(metrics) + '\n', encoding='utf-8')
print(text_path.read_text(encoding='utf-8'))
PY

if [[ -n "${PUSHGATEWAY_URL}" ]]; then
  curl --fail --silent --show-error \
    --request PUT \
    --data-binary @"${METRICS_FILE}" \
    "${PUSHGATEWAY_URL%/}/metrics/job/${PUSHGATEWAY_JOB}/suite/lesavka/gate/supply-chain" || status=$?
fi

exit "${status}"
