#!/bin/bash
# Fixes up icons that 10-generate-app-icons.sh's algorithmic trace got
# wrong -- specifically icon packs that draw a colored "badge" background
# UNDER an equally-opaque foreground glyph (kora's app icons, mostly),
# which potrace + alpha/dominant-color heuristics can't reliably separate
# (both are fully opaque, just different colors) and so ends up tracing
# as a solid blob or a thin outline.
#
# Runs ENTIRELY on this host (eurobuild6) -- the one place Ollama is
# installed -- never on the target. For each icon whose cached silhouette
# in generated_icons/silhouettes/ measures as degenerate (near-empty or
# near-solid alpha coverage), fetches that icon's real SVG source from the
# target (recorded in generated_icons/manifest.json), asks a local coder
# LLM to structurally separate badge from glyph, and strictly validates
# the result before accepting it: every kept element's geometry (d,
# points, cx/cy/r, x/y/width/height, transform) must appear byte-for-byte
# in the original, or the result is rejected and the existing algorithmic
# trace is left untouched. See lib/icon_llm_refine.py for the full
# reasoning. A rejection is always a safe no-op, never corruption.
#
# This is a one-time enrichment pass over whatever's already in
# generated_icons/ -- its output is cached into the same silhouette files
# everything else uses, so the deployed machine needs no AI/Ollama at all;
# ./11-deploy-icon-theme.sh is what actually ships the result.
#
# Usage: 13-llm-refine-icons.sh --vm [--model NAME] [--force <icon-name> ...] [--force-all]
#   --vm only -- Ollama runs on whichever host executes this script, not on
#   the target, so "--local" would mean installing Ollama + a coder model
#   on a laptop you've gone out of your way to keep Ollama-free (see
#   README.md). Trace new apps against the VM, then ship the refined cache
#   to the laptop like any other icon update.
#   --model: Ollama model to use (default: qwen2.5-coder:7b).
#   --force <name>: also attempt refinement on a specific icon even if its
#                   current trace doesn't measure as degenerate.
#   --force-all: attempt refinement on every SVG-sourced icon in the manifest.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./00-config.sh

MODEL="qwen2.5-coder:7b"
FORCE_NAMES=()
FORCE_ALL=0
parse_target_flag "$@"
set -- "${PARSED_ARGS[@]+"${PARSED_ARGS[@]}"}"
while [ $# -gt 0 ]; do
    case "$1" in
        --model) shift; MODEL="$1" ;;
        --force-all) FORCE_ALL=1 ;;
        --force) shift; FORCE_NAMES+=("$1") ;;
        *) echo "Unknown argument: $1" >&2; exit 1 ;;
    esac
    shift
done

if [ "$TARGET" = "local" ]; then
    echo "13-llm-refine-icons.sh is --vm only -- see the usage comment at the top" >&2
    echo "of this file for why. Run against --vm instead." >&2
    exit 1
fi

if ! command -v ollama >/dev/null 2>&1; then
    echo "ollama is not installed on this host -- this script only runs locally, never on the target." >&2
    exit 1
fi
if ! curl -s -o /dev/null --max-time 5 http://localhost:11434/api/tags; then
    echo "Ollama's API isn't responding on http://localhost:11434 -- is the service running?" >&2
    exit 1
fi

GEN_DIR="../generated_icons"
SILHOUETTE_DIR="${GEN_DIR}/silhouettes"
MANIFEST="${GEN_DIR}/manifest.json"

if [ ! -f "$MANIFEST" ]; then
    echo "No ${MANIFEST} -- run ./10-generate-app-icons.sh first." >&2
    exit 1
fi

WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
mkdir -p "${WORK}/sources"

echo ">>> Target (for fetching original SVG sources): ${TARGET}"
echo ">>> Model: ${MODEL}"

echo ">>> [1/3] Scanning cached silhouettes for degenerate traces"
python3 ./lib/icon_llm_refine.py scan --silhouette-dir "$SILHOUETTE_DIR" > "${WORK}/candidates.txt"

if [ "$FORCE_ALL" = 1 ]; then
    python3 -c "
import json
m = json.load(open('${MANIFEST}'))
for n in sorted(m):
    print(n)
" > "${WORK}/candidates.txt"
else
    for n in "${FORCE_NAMES[@]+"${FORCE_NAMES[@]}"}"; do
        echo -e "${n}\t(forced)" >> "${WORK}/candidates.txt"
    done
fi
sort -u -o "${WORK}/candidates.txt" "${WORK}/candidates.txt"

CANDIDATE_COUNT=$(wc -l < "${WORK}/candidates.txt")
echo "    ${CANDIDATE_COUNT} candidate(s)"
if [ "$CANDIDATE_COUNT" -eq 0 ]; then
    echo ">>> Nothing looks degenerate. Done."
    exit 0
fi
cut -f1 "${WORK}/candidates.txt"

echo ">>> [2/3] Fetching each candidate's real SVG source from the target"
# Read names into an array first, not a `while read ... done < file` loop --
# `run`'s ssh call would otherwise consume the loop's own stdin (the rest
# of candidates.txt) on its first iteration, silently truncating the loop.
mapfile -t CANDIDATE_NAMES < <(cut -f1 "${WORK}/candidates.txt")
for name in "${CANDIDATE_NAMES[@]}"; do
    [ -z "$name" ] && continue
    SRC_PATH=$(python3 -c "
import json
m = json.load(open('${MANIFEST}'))
e = m.get('${name}', {})
rp = e.get('source_path', '')
print(rp if rp.lower().endswith('.svg') else '')
")
    if [ -z "$SRC_PATH" ]; then
        continue  # PNG-sourced or unknown -- icon_llm_refine.py's refine step reports this as skipped
    fi
    run "cat '${SRC_PATH}'" < /dev/null > "${WORK}/sources/${name}.svg" 2>/dev/null || rm -f "${WORK}/sources/${name}.svg"
done
echo "    $(find "${WORK}/sources" -name '*.svg' | wc -l) source(s) fetched"

echo ">>> [3/3] Asking ${MODEL} to separate badge from glyph, per candidate"
python3 ./lib/icon_llm_refine.py refine \
    --manifest "$MANIFEST" \
    --silhouette-dir "$SILHOUETTE_DIR" \
    --sources-dir "${WORK}/sources" \
    --candidates "${WORK}/candidates.txt" \
    --model "$MODEL"

echo ">>> Done. Run ./11-deploy-icon-theme.sh to install the refined icons."
