#!/usr/bin/env bash
# Plukker neste ugjorte oppgave fra tasks.md og starter en Claude Code-sesjon.
# Hopper over oppgaver som er pågående [~], har åpent spørsmål [?], eller
# er blokkert [!], inkludert alle oppgaver som avhenger av dem.
#
# Støtter parallell kjøring: markerer oppgaven som [~] (pågår) før start,
# setter den til [x] eller tilbake til [ ] avhengig av resultat.
#
# Bruk:
#   ./scripts/run-next-task.sh              # kjør neste oppgave
#   ./scripts/run-next-task.sh --dry        # vis hvilken oppgave som er neste
#   ./scripts/run-next-task.sh --status     # vis status for alle oppgaver
#   ./scripts/run-next-task.sh --unstale    # frigjør [~] oppgaver eldre enn 60 min

set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
TASKS="$ROOT/tasks.md"

# --- Avhengighetskart: fase → faser den avhenger av ---
declare -A PHASE_DEPS=(
    [1]=""
    [2]="1"
    [3]="2"
    [4]="2"
    [5]="3 4"
    [6]="2"
    [7]="6"
    [8]="5"
    [9]="3"
    [10]="2"
    [11]="5 6 7"
    [12]="1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 17 18 19 20 21"
    [13]="3 4"
    [14]="6 13"
    [15]="3 10"
    [16]="11 13"
    [17]=""
    [18]="10 13"
    [19]="3 13"
    [20]="19"
    [21]="2"
    [22]="12"
    [23]="22"
    [24]="23"
    [25]="24"
    [26]="25"
    [27]="25"
    [28]="25"
    [29]="25"
    [30]="25"
)

# --- Finn blokkerte faser ---
# En fase er blokkert hvis den har en [?], [!] eller [~] oppgave
blocked_phases() {
    local phases=""
    for phase in $(seq 1 21); do
        if grep -qP "^\- \[(\?|!|~)\] ${phase}\." "$TASKS" 2>/dev/null; then
            phases="$phases $phase"
        fi
    done
    echo "$phases"
}

# Sjekk om en fase er tilgjengelig
phase_available() {
    local phase=$1
    local blocked="$2"

    # Sjekk om denne fasen selv er blokkert
    if echo "$blocked" | grep -qw "$phase"; then
        return 1
    fi

    # Sjekk om avhengige faser er blokkert eller har ugjorte oppgaver
    local deps="${PHASE_DEPS[$phase]}"
    for dep in $deps; do
        if echo "$blocked" | grep -qw "$dep"; then
            return 1
        fi
        # Sjekk at alle oppgaver i avhengig fase er ferdige
        if grep -qP "^\- \[ \] ${dep}\." "$TASKS" 2>/dev/null; then
            return 1
        fi
    done

    return 0
}

# Sjekk at forrige oppgave i samme fase er ferdig
prev_task_done() {
    local task_id=$1  # f.eks. "2.4"
    local phase=$(echo "$task_id" | cut -d. -f1)
    local num=$(echo "$task_id" | cut -d. -f2)

    if [[ "$num" == "1" ]]; then
        return 0  # Første oppgave i fasen, ingen forrige
    fi

    local prev_num=$((num - 1))
    local prev_id="${phase}.${prev_num}"

    # Forrige oppgave må være [x]
    if grep -qP "^\- \[x\] ${prev_id} " "$TASKS" 2>/dev/null; then
        return 0
    fi
    return 1
}

# --- Frigjør stale [~] oppgaver ---
if [[ "${1:-}" == "--unstale" ]]; then
    echo "Sjekker etter stale [~] oppgaver (>60 min)..."
    now=$(date +%s)
    changed=false
    while IFS= read -r line; do
        # Hent timestamp fra linjen under (> Påbegynt: 2026-03-17T14:30)
        line_num=$(echo "$line" | cut -d: -f1)
        next_line=$((line_num + 1))
        ts=$(sed -n "${next_line}p" "$TASKS" | grep -oP '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}' || echo "")
        if [[ -n "$ts" ]]; then
            started=$(date -d "$ts" +%s 2>/dev/null || echo 0)
            elapsed=$(( (now - started) / 60 ))
            if [[ $elapsed -gt 60 ]]; then
                task_text=$(echo "$line" | cut -d: -f2-)
                echo "  Frigjør (${elapsed} min gammel): $task_text"
                sed -i "${line_num}s/^\- \[~\]/- [ ]/" "$TASKS"
                sed -i "${next_line}d" "$TASKS"  # Fjern påbegynt-linjen
                changed=true
            fi
        fi
    done < <(grep -n '^\- \[~\]' "$TASKS")
    if $changed; then
        echo "Oppdatert. Commit manuelt om ønsket."
    else
        echo "Ingen stale oppgaver funnet."
    fi
    exit 0
fi

# --- Status-visning ---
if [[ "${1:-}" == "--status" ]]; then
    echo "=== Synops oppgavestatus ==="
    echo ""
    done=$(grep -cP '^\- \[x\]' "$TASKS" || true)
    todo=$(grep -cP '^\- \[ \]' "$TASKS" || true)
    in_progress=$(grep -cP '^\- \[~\]' "$TASKS" || true)
    questions=$(grep -cP '^\- \[\?\]' "$TASKS" || true)
    blocked_count=$(grep -cP '^\- \[!\]' "$TASKS" || true)
    done=${done:-0}; todo=${todo:-0}; in_progress=${in_progress:-0}
    questions=${questions:-0}; blocked_count=${blocked_count:-0}
    total=$((done + todo + in_progress + questions + blocked_count))
    echo "Ferdige:   $done / $total"
    echo "Pågår:     $in_progress"
    echo "Gjenstår:  $todo"
    echo "Spørsmål:  $questions"
    echo "Blokkert:  $blocked_count"
    echo ""
    if [[ $in_progress -gt 0 ]]; then
        echo "--- Pågår ---"
        grep -A1 '^\- \[~\]' "$TASKS" || true
        echo ""
    fi
    if [[ $questions -gt 0 ]]; then
        echo "--- Åpne spørsmål ---"
        grep -A2 '^\- \[\?\]' "$TASKS" || true
        echo ""
    fi
    if [[ $blocked_count -gt 0 ]]; then
        echo "--- Blokkerte oppgaver ---"
        grep -A2 '^\- \[!\]' "$TASKS" || true
    fi
    exit 0
fi

# --- Finn neste oppgave ---
blocked=$(blocked_phases)

next_task=""
line_num=""
task_text=""
task_id=""

while IFS= read -r line; do
    num=$(echo "$line" | cut -d: -f1)
    text=$(echo "$line" | cut -d: -f2- | sed 's/^- \[ \] //')
    # Hent oppgave-ID (f.eks. "1.3")
    id=$(echo "$text" | grep -oP '^\d+\.\d+' || echo "")
    phase=$(echo "$text" | grep -oP '^\d+' || echo "")

    if [[ -n "$phase" ]] && phase_available "$phase" "$blocked" && prev_task_done "$id"; then
        next_task="$line"
        line_num="$num"
        task_text="$text"
        task_id="$id"
        break
    fi
done < <(grep -n '^\- \[ \]' "$TASKS")

if [[ -z "$next_task" ]]; then
    if [[ -n "$blocked" ]]; then
        echo "Ingen tilgjengelige oppgaver. Blokkerte/pågående faser:$blocked"
        echo "Kjør --status for detaljer."
    else
        echo "Alle oppgaver er gjort!"
    fi
    exit 0
fi

echo "Neste oppgave (linje $line_num):"
echo "  $task_text"
echo ""

if [[ "${1:-}" == "--dry" ]]; then
    exit 0
fi

# --- Marker oppgaven som pågående ---
timestamp=$(date +%Y-%m-%dT%H:%M)
sed -i "${line_num}s/^\- \[ \]/- [~]/" "$TASKS"
sed -i "${line_num}a\\  > Påbegynt: ${timestamp}" "$TASKS"
cd "$ROOT"
git add tasks.md
git commit -m "Starter oppgave ${task_id}" --no-verify 2>/dev/null || true
git push origin main 2>/dev/null || true

# --- Bygg prompt ---
PROMPT="Du skal implementere neste oppgave i Synops-prosjektet.
Du jobber autonomt — ingen bruker er tilgjengelig for spørsmål underveis.

## Oppgave
$task_text

## Arbeidsflyt

1. **Orienter deg.** Les \`CLAUDE.md\` for prosjektkontekst. Les dokumentene
   som refereres i oppgaven. Les \`tasks.md\` for å forstå hvor prosjektet står
   (hvilke oppgaver er ferdige, hva er tilgjengelig).
2. **Pull siste endringer.** Kjør \`git pull origin main\` først — andre
   agenter kan ha pushet endringer.
3. **Implementer.** Skriv kode. Du kjører direkte på serveren — bygg, test og deploy her.
4. **Verifiser.** Kompilering, curl-test, kjør relevante tester.
5. **Oppdater dokumentasjon.** Hvis implementeringen avviker fra eksisterende
   docs, oppdater dem. Nye tekniske beslutninger dokumenteres i relevante
   filer under \`docs/\`. Docs skal alltid reflektere faktisk tilstand.
6. **Oppdater tasks.md.** Endre \`- [~]\` til \`- [x]\` for oppgave ${task_id}.
   Fjern \`> Påbegynt: ...\`-linjen under oppgaven.
7. **Commit og push.** Commit alle endringer (kode + docs + tasks.md) med
   en beskrivende melding. Push til forgejo (\`git push origin main\`).
   Flere commits underveis er OK — push jevnlig så andre agenter ser fremgangen.

## Hvis noe blokkerer

Hvis du trenger avklaring fra Vegard:
- Endre oppgavens status fra \`- [~]\` til \`- [?]\` i tasks.md
- Fjern påbegynt-linjen, legg til spørsmålet:
  \`\`\`
  - [?] ${task_id} ...
    > Spørsmål: <ditt spørsmål>
    > Kontekst: <hvorfor dette er uklart>
  \`\`\`
- Commit og push. Avslutt sesjonen.

Hvis du støter på et teknisk problem du ikke kan løse:
- Endre status fra \`- [~]\` til \`- [!]\` i tasks.md
- Dokumenter problemet. Commit og push. Avslutt.

## Regler

- Jobb kun på oppgave ${task_id}. Ikke start på neste.
- Ikke deploy til produksjon uten eksplisitt godkjenning.
- Følg eksisterende arkitektur og konvensjoner i \`docs/\`.
- Hold det enkelt — minimum viable for oppgaven.
- Dokumentasjon er like viktig som kode. Neste sesjon har ingen kontekst
  fra denne — alt den vet kommer fra kode, docs og git-historikk.
- Skriv commit-meldinger som forklarer *hvorfor*, ikke bare *hva*.
- Push jevnlig underveis — ikke samle opp alt til slutt.
- Du kan spinne opp subagenter (Agent-tool) for parallelt arbeid der det
  er egnet — f.eks. research i docs, utforske kodebasen, eller kjøre
  uavhengige deloppgaver samtidig. Bruk det aktivt for å jobbe effektivt."

# --- Velg modell og effort basert på fase ---
CLAUDE_ARGS="--dangerously-skip-permissions"
phase_num="${task_id%%.*}"
case "$phase_num" in
    23) # Validering krever grundig gjennomgang
        CLAUDE_ARGS="$CLAUDE_ARGS --model claude-opus-4-6"
        echo "Fase 23 (validering): bruker Opus med høy effort"
        ;;
esac

echo "Starter Claude Code-sesjon for oppgave ${task_id}..."
cd "$ROOT"
claude -p $CLAUDE_ARGS "$PROMPT"
exit_code=$?

# --- Hvis claude krasjer, sett oppgaven tilbake til [ ] ---
if [[ $exit_code -ne 0 ]]; then
    echo "Claude-sesjonen feilet (exit code $exit_code). Tilbakestiller oppgave ${task_id}."
    # Sjekk om oppgaven fortsatt er [~] (ikke allerede endret av sesjonen)
    if grep -qP "^\- \[~\] ${task_id} " "$TASKS"; then
        sed -i "/^\- \[~\] ${task_id} /s/^\- \[~\]/- [ ]/" "$TASKS"
        # Fjern påbegynt-linjen
        line_after=$(grep -n "^\- \[ \] ${task_id} " "$TASKS" | cut -d: -f1)
        if [[ -n "$line_after" ]]; then
            next=$((line_after + 1))
            if sed -n "${next}p" "$TASKS" | grep -q '> Påbegynt:'; then
                sed -i "${next}d" "$TASKS"
            fi
        fi
        git add tasks.md
        git commit -m "Tilbakestill oppgave ${task_id} etter feilet sesjon" --no-verify 2>/dev/null || true
        git push origin main 2>/dev/null || true
    fi
fi
