#!/usr/bin/env bash
# Seed the curated demo targets (#187) into a running compliance-agent.
#
# Reads fixtures/demo-targets/targets.json and, for every target:
#   1. POST /api/v1/targets                       (name = name_prefix + name)
#   2. POST /api/v1/targets/{id}/artifacts/upload  for each `upload` artifact
#   3. POST /api/v1/targets/{id}/detect            (surface detected facts)
#   4. POST /api/v1/targets/{id}/scan              (only with --scan)
#
# Artifact env overrides (see the manifest): DEMO_WEB_URL, DEMO_PLC_MODBUS_URL,
# DEMO_PLC_FIRMWARE_IMAGE. Optional artifacts whose env var is unset are
# skipped, so the set seeds on a bare laptop; set them on comp-dev / Orca.
#
# Usage:
#   scripts/seed-demo-targets.sh                 # seed all
#   scripts/seed-demo-targets.sh --scan          # seed + trigger first scan
#   scripts/seed-demo-targets.sh --only web-juice-shop,git-cra-vuln-demo
#   scripts/seed-demo-targets.sh --reset         # delete every "Demo · " target
#   scripts/seed-demo-targets.sh --reset --scan  # reset, reseed, scan
#
# Env:
#   AGENT_URL    base URL of the agent            (default http://localhost:3011)
#   AGENT_TOKEN  bearer token; omit for dev mode  (no Keycloak → dev tenant)
#   MANIFEST     alternative manifest path

set -euo pipefail

AGENT_URL="${AGENT_URL:-http://localhost:3011}"
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MANIFEST="${MANIFEST:-$ROOT/fixtures/demo-targets/targets.json}"

DO_SCAN=0
DO_RESET=0
ONLY=""
while [[ $# -gt 0 ]]; do
    case "$1" in
        --scan) DO_SCAN=1 ;;
        --reset) DO_RESET=1 ;;
        --only) ONLY="$2"; shift ;;
        -h|--help) sed -n '2,25p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
        *) echo "unknown arg: $1" >&2; exit 2 ;;
    esac
    shift
done

for bin in jq curl; do
    command -v "$bin" >/dev/null || { echo "need $bin" >&2; exit 1; }
done
[[ -f "$MANIFEST" ]] || { echo "manifest not found: $MANIFEST" >&2; exit 1; }

AUTH=()
[[ -n "${AGENT_TOKEN:-}" ]] && AUTH=(-H "Authorization: Bearer ${AGENT_TOKEN}")

green() { printf '\033[32m%s\033[0m' "$*"; }
yellow() { printf '\033[33m%s\033[0m' "$*"; }
red() { printf '\033[31m%s\033[0m' "$*"; }

# api METHOD PATH [curl args...] → body on stdout; non-2xx → exit 1 with body.
api() {
    local method="$1" path="$2"; shift 2
    local out code
    out=$(curl -sS -X "$method" "${AGENT_URL}${path}" "${AUTH[@]}" -w '\n%{http_code}' "$@")
    code="${out##*$'\n'}"
    out="${out%$'\n'*}"
    if [[ "$code" != 2* ]]; then
        echo "$(red "HTTP $code") $method $path" >&2
        echo "$out" >&2
        return 1
    fi
    printf '%s' "$out"
}

PREFIX="$(jq -r '.name_prefix' "$MANIFEST")"

reset_targets() {
    echo "== reset: deleting targets named '${PREFIX}*'"
    local list ids
    list=$(api GET "/api/v1/targets?limit=500")
    ids=$(jq -r --arg p "$PREFIX" '.data[] | select(.name | startswith($p)) | ._id."$oid"' <<<"$list")
    local n=0
    for id in $ids; do
        api DELETE "/api/v1/targets/${id}" >/dev/null && n=$((n + 1))
    done
    echo "   deleted $n"
}

# Build the JSON artifact list for reference-style (non-upload) artifacts.
# Prints one JSON object per artifact that should be created inline.
inline_artifacts() {
    local target_json="$1"
    jq -c '.artifacts[] | select(.upload == null and .upload_env == null)' <<<"$target_json" |
    while IFS= read -r a; do
        local kind env ref optional branch
        kind=$(jq -r '.kind' <<<"$a")
        env=$(jq -r '.source_ref_env // empty' <<<"$a")
        ref=$(jq -r '.source_ref // empty' <<<"$a")
        optional=$(jq -r '.optional // false' <<<"$a")
        branch=$(jq -r '.branch // empty' <<<"$a")
        if [[ -n "$env" && -n "${!env:-}" ]]; then
            ref="${!env}"
        elif [[ -n "$env" && "$optional" == "true" ]]; then
            echo "   $(yellow skip) $kind (set \$$env to include)" >&2
            continue
        fi
        [[ -n "$ref" ]] || continue
        jq -cn --arg k "$kind" --arg r "$ref" --arg b "$branch" \
            '{kind:$k, source_ref:$r} + (if $b != "" then {branch:$b} else {} end)'
    done
}

# Upload every `upload` / `upload_env` artifact of the target.
upload_artifacts() {
    local id="$1" target_json="$2"
    jq -c '.artifacts[] | select(.upload != null or .upload_env != null)' <<<"$target_json" |
    while IFS= read -r a; do
        local kind path env fmt optional
        kind=$(jq -r '.kind' <<<"$a")
        env=$(jq -r '.upload_env // empty' <<<"$a")
        path=$(jq -r '.upload // empty' <<<"$a")
        fmt=$(jq -r '.plc_format // empty' <<<"$a")
        optional=$(jq -r '.optional // false' <<<"$a")
        if [[ -n "$env" && -n "${!env:-}" ]]; then
            path="${!env}"
        elif [[ -n "$path" ]]; then
            path="$ROOT/$path"
        elif [[ "$optional" == "true" ]]; then
            echo "   $(yellow skip) $kind (set \$$env to include)" >&2
            continue
        fi
        [[ -f "$path" ]] || { echo "   $(red missing) $path" >&2; return 1; }
        local form=(-F "file=@${path}" -F "kind=${kind}")
        [[ -n "$fmt" ]] && form+=(-F "plc_format=${fmt}")
        api POST "/api/v1/targets/${id}/artifacts/upload" "${form[@]}" >/dev/null
        echo "   $(green upload) $kind $(basename "$path")"
    done
}

seed_target() {
    local t="$1"
    local key name type desc
    key=$(jq -r '.key' <<<"$t")
    name="${PREFIX}$(jq -r '.name' <<<"$t")"
    type=$(jq -r '.target_type' <<<"$t")
    desc=$(jq -r '.description // ""' <<<"$t")
    echo "== $key  ($type)"

    local arts body resp id
    arts=$(inline_artifacts "$t" | jq -cs '.')
    body=$(jq -cn --arg n "$name" --arg tt "$type" --arg d "$desc" --argjson a "$arts" \
        '{name:$n, target_type:$tt, description:$d, artifacts:$a}')
    resp=$(api POST "/api/v1/targets" -H 'Content-Type: application/json' -d "$body")
    id=$(jq -r '.data._id."$oid"' <<<"$resp")
    echo "   $(green created) $id  $(jq -r '.data.artifacts|length' <<<"$resp") inline artifact(s)"

    upload_artifacts "$id" "$t"

    local det
    det=$(api POST "/api/v1/targets/${id}/detect" -H 'Content-Type: application/json' -d '{}' || true)
    if [[ -n "$det" ]]; then
        echo "   detect → $(jq -r '.data.classification.suggested // "n/a"' <<<"$det")"
    fi

    if [[ "$DO_SCAN" == 1 ]]; then
        api POST "/api/v1/targets/${id}/scan" -H 'Content-Type: application/json' -d '{}' >/dev/null
        echo "   $(green scan) triggered"
    fi
}

[[ "$DO_RESET" == 1 ]] && reset_targets

echo "== seeding from $MANIFEST → $AGENT_URL"
jq -c '.targets[]' "$MANIFEST" | while IFS= read -r t; do
    key=$(jq -r '.key' <<<"$t")
    if [[ -n "$ONLY" && ",$ONLY," != *",$key,"* ]]; then
        continue
    fi
    seed_target "$t"
done
echo "== done"
