#!/usr/bin/env bash
# ── Kimi Agent Loop ────────────────────────────────────────────────────
# Polls Gitea for issues assigned to kimi. For each one:
#   1. Creates worktree + branch
#   2. Runs kimi CLI with the issue as context
#   3. Tests (tox -e unit)
#   4. Pushes branch, opens PR
#   5. Unassigns self if done
#
# Communication is through Gitea. No tmux coordination with Hermes.
# ───────────────────────────────────────────────────────────────────────

set -uo pipefail
export PATH="/opt/homebrew/bin:$HOME/.local/bin:$HOME/.hermes/bin:/usr/local/bin:$PATH"

REPO="rockachopa/Timmy-time-dashboard"
CANONICAL="$HOME/Timmy-Time-dashboard"
WORKTREE_BASE="$HOME/worktrees"
KIMI_TOKEN=$(cat "$HOME/.hermes/kimi_token")
HERMES_TOKEN=$(cat "$HOME/.hermes/gitea_token")
API="http://localhost:3000/api/v1"
MAX_CYCLE_TIME=900  # 15 min per issue
POLL_INTERVAL=120   # Check every 2 min

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}

# ── Git identity for kimi ──────────────────────────────────────────────
setup_git_identity() {
    local workdir="$1"
    cd "$workdir"
    git config user.name "kimi"
    git config user.email "kimi@localhost"
    # Set push URL with kimi's token
    git remote set-url origin "http://kimi:${KIMI_TOKEN}@localhost:3000/${REPO}.git"
}

# ── Fetch assigned issues ──────────────────────────────────────────────
get_assigned_issues() {
    curl -s "${API}/repos/${REPO}/issues?assignee=kimi&state=open&type=issues&sort=priority&direction=asc&limit=5&token=${KIMI_TOKEN}"
}

# ── Create worktree for an issue ───────────────────────────────────────
create_worktree() {
    local issue_number="$1"
    local branch="kimi/issue-${issue_number}"
    local workdir="${WORKTREE_BASE}/kimi-${issue_number}"

    mkdir -p "$WORKTREE_BASE"

    # Clean up stale worktree if exists
    if [ -d "$workdir" ]; then
        cd "$CANONICAL"
        git worktree remove "$workdir" --force 2>/dev/null || rm -rf "$workdir"
    fi

    # Fetch latest main
    cd "$CANONICAL"
    git fetch origin main 2>/dev/null

    # Create branch and worktree
    git branch -D "$branch" 2>/dev/null || true
    git worktree add -b "$branch" "$workdir" origin/main 2>/dev/null

    if [ ! -d "$workdir" ]; then
        log "ERROR: Failed to create worktree at $workdir"
        return 1
    fi

    setup_git_identity "$workdir"
    echo "$workdir"
}

# ── Run kimi on an issue ───────────────────────────────────────────────
work_issue() {
    local issue_number="$1"
    local issue_title="$2"
    local issue_body="$3"
    local workdir="$4"
    local branch="kimi/issue-${issue_number}"

    log "Working on #${issue_number}: ${issue_title}"

    # Comment that kimi is starting work
    curl -s -X POST "${API}/repos/${REPO}/issues/${issue_number}/comments?token=${KIMI_TOKEN}" \
        -H "Content-Type: application/json" \
        -d "{\"body\": \"Kimi picking this up. Working in branch \`${branch}\`.\"}" >/dev/null

    # Build the prompt for kimi
    local prompt="You are Kimi, an AI coding agent. Fix issue #${issue_number} in the Timmy-time-dashboard repo.

ISSUE: ${issue_title}

DESCRIPTION:
${issue_body}

WORKSPACE: ${workdir}
BRANCH: ${branch}

RULES:
- Work ONLY in the workspace directory
- Make focused, minimal changes — do not refactor unrelated code
- Run 'tox -e unit' before committing — tests MUST pass
- Run 'tox -e lint' before committing — no new lint errors
- Commit with a descriptive message referencing #${issue_number}
- Do NOT push or create PRs — the loop script handles that
- If the issue is unclear or too large, just add a comment explaining why and exit"

    # Write prompt and run kimi
    local prompt_file="${workdir}/.kimi-prompt.txt"
    echo "$prompt" > "$prompt_file"

    cd "$workdir"

    # Run kimi with timeout
    timeout "${MAX_CYCLE_TIME}" kimi --print-file "$prompt_file" 2>&1 | tee "${workdir}/.kimi-output.log"
    local exit_code=$?

    if [ $exit_code -ne 0 ]; then
        log "WARN: kimi exited with code $exit_code on #${issue_number}"
    fi

    return $exit_code
}

# ── Test, push, and PR ─────────────────────────────────────────────────
submit_work() {
    local issue_number="$1"
    local issue_title="$2"
    local workdir="$3"
    local branch="kimi/issue-${issue_number}"

    cd "$workdir"

    # Check if there are any commits beyond origin/main
    local new_commits
    new_commits=$(git log origin/main..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')

    if [ "$new_commits" -eq 0 ]; then
        log "No commits on #${issue_number} — kimi produced no changes"
        curl -s -X POST "${API}/repos/${REPO}/issues/${issue_number}/comments?token=${KIMI_TOKEN}" \
            -H "Content-Type: application/json" \
            -d '{"body": "No changes produced. May need different approach or more context."}' >/dev/null
        return 1
    fi

    # Run tests
    log "Running tests for #${issue_number}..."
    if ! tox -e unit -q 2>&1 | tail -5; then
        log "Tests FAILED on #${issue_number} — not submitting PR"
        curl -s -X POST "${API}/repos/${REPO}/issues/${issue_number}/comments?token=${KIMI_TOKEN}" \
            -H "Content-Type: application/json" \
            -d '{"body": "Tests failed on my branch. Leaving for manual review or retry."}' >/dev/null
        return 1
    fi

    # Run lint
    log "Running lint for #${issue_number}..."
    if ! tox -e lint -q 2>&1 | tail -5; then
        log "Lint FAILED on #${issue_number} — not submitting PR"
        curl -s -X POST "${API}/repos/${REPO}/issues/${issue_number}/comments?token=${KIMI_TOKEN}" \
            -H "Content-Type: application/json" \
            -d '{"body": "Lint check failed on my branch. Leaving for manual review or retry."}' >/dev/null
        return 1
    fi

    # Push
    log "Pushing branch ${branch}..."
    if ! git push --no-verify origin "$branch" 2>&1; then
        log "Push FAILED on #${issue_number}"
        return 1
    fi

    # Create PR
    log "Creating PR for #${issue_number}..."
    local pr_body="Fixes #${issue_number}

$(git log origin/main..HEAD --format='- %s' 2>/dev/null)

---
*Authored by kimi-agent. Tests and lint pass.*"

    local pr_response
    pr_response=$(curl -s -X POST "${API}/repos/${REPO}/pulls?token=${KIMI_TOKEN}" \
        -H "Content-Type: application/json" \
        -d "{
            \"title\": \"[kimi] ${issue_title} (#${issue_number})\",
            \"body\": $(echo "$pr_body" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))'),
            \"head\": \"${branch}\",
            \"base\": \"main\",
            \"assignees\": [\"hermes\"]
        }")

    local pr_number
    pr_number=$(echo "$pr_response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read()).get('number','FAIL'))" 2>/dev/null)

    if [ "$pr_number" = "FAIL" ]; then
        log "PR creation FAILED on #${issue_number}: $pr_response"
        return 1
    fi

    log "PR #${pr_number} created for issue #${issue_number}"

    # Comment on the issue
    curl -s -X POST "${API}/repos/${REPO}/issues/${issue_number}/comments?token=${KIMI_TOKEN}" \
        -H "Content-Type: application/json" \
        -d "{\"body\": \"PR #${pr_number} submitted. Tests and lint pass. Assigned to hermes for review.\"}" >/dev/null

    return 0
}

# ── Cleanup worktree ───────────────────────────────────────────────────
cleanup_worktree() {
    local issue_number="$1"
    local workdir="${WORKTREE_BASE}/kimi-${issue_number}"

    cd "$CANONICAL"
    git worktree remove "$workdir" --force 2>/dev/null || rm -rf "$workdir"
}

# ── Main loop ──────────────────────────────────────────────────────────

log "=== Kimi Agent Loop started ==="
log "Polling ${API}/repos/${REPO}/issues?assignee=kimi every ${POLL_INTERVAL}s"

while true; do
    # Fetch assigned issues
    issues_json=$(get_assigned_issues)

    # Parse issues
    issue_count=$(echo "$issues_json" | python3 -c "
import json, sys
try:
    issues = json.loads(sys.stdin.read())
    print(len(issues) if isinstance(issues, list) else 0)
except:
    print(0)
" 2>/dev/null)

    if [ "$issue_count" -gt 0 ]; then
        # Take the first (highest priority) issue
        read -r issue_number issue_title <<< "$(echo "$issues_json" | python3 -c "
import json, sys
issues = json.loads(sys.stdin.read())
i = issues[0]
# Escape title for shell
title = i['title'].replace('\"', '').replace('\`', '')[:80]
print(f\"{i['number']} {title}\")
" 2>/dev/null)"

        issue_body=$(echo "$issues_json" | python3 -c "
import json, sys
issues = json.loads(sys.stdin.read())
body = issues[0].get('body', '')[:2000]
print(body)
" 2>/dev/null)

        log "Found issue #${issue_number}: ${issue_title}"

        # Create worktree
        workdir=$(create_worktree "$issue_number")

        if [ -n "$workdir" ] && [ -d "$workdir" ]; then
            # Do the work
            work_issue "$issue_number" "$issue_title" "$issue_body" "$workdir"

            # Submit if there's work
            submit_work "$issue_number" "$issue_title" "$workdir"

            # Clean up
            cleanup_worktree "$issue_number"
        fi
    else
        log "No assigned issues. Sleeping."
    fi

    sleep "$POLL_INTERVAL"
done
