<script lang="ts">
  import type { PendingApproval } from '$lib/stores/chat'
  import { decideApproval } from '$lib/api'
  import { Button } from '$lib/components/ui/button'
  import { SvelteMap } from 'svelte/reactivity'
  import CheckIcon from '@lucide/svelte/icons/check'
  import XIcon from '@lucide/svelte/icons/x'
  import ShieldCheckIcon from '@lucide/svelte/icons/shield-check'
  import LoaderCircleIcon from '@lucide/svelte/icons/loader-circle'

  let { approvals }: { approvals: PendingApproval[] } = $props()

  // Per-execution outcome, keyed by executionId. A resolved entry hides the
  // action buttons for that approval permanently so the banner clears after a
  // click and can never re-POST /decision. 'pending' guards against double
  // submits (the old component reset its state on every prop change, so the
  // banner never cleared and each click fired another decision).
  type State = 'pending' | 'approved' | 'denied' | 'failed'
  const outcome = new SvelteMap<string, State>()

  async function decide(approval: PendingApproval, decision: 'approve' | 'deny') {
    const id = approval.executionId
    const cur = outcome.get(id)
    if (cur === 'pending' || cur === 'approved' || cur === 'denied') return // no resubmit
    outcome.set(id, 'pending')
    const ok = await decideApproval(id, decision)
    outcome.set(id, ok ? (decision === 'approve' ? 'approved' : 'denied') : 'failed')
  }
</script>

{#each approvals as approval (approval.executionId)}
  {@const state = outcome.get(approval.executionId)}
  {#if state === 'approved'}
    <div class="my-2 flex items-center gap-2 rounded-lg border border-success/40 bg-success/5 px-3 py-2 text-xs text-success">
      <CheckIcon class="size-4" />
      <span>Approved — provisioning. Track progress in the Executions view.</span>
    </div>
  {:else if state === 'denied'}
    <div class="my-2 flex items-center gap-2 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive">
      <XIcon class="size-4" />
      <span>Denied.</span>
    </div>
  {:else if state === 'failed'}
    <div class="my-2 flex items-center gap-2 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive">
      <XIcon class="size-4" />
      <span class="flex-1">Decision failed to send.</span>
      <Button size="sm" variant="outline" class="h-7 px-2.5 text-xs" onclick={() => { outcome.delete(approval.executionId); decide(approval, 'approve') }}>
        Retry
      </Button>
    </div>
  {:else}
    <div class="my-2 flex items-center gap-2 rounded-lg border border-warning/40 bg-warning/5 px-3 py-2">
      <ShieldCheckIcon class="size-4 shrink-0 text-warning" />
      <span class="flex-1 text-xs text-muted-foreground">
        {approval.action} on {approval.target} requires approval
      </span>
      {#if state === 'pending'}
        <LoaderCircleIcon class="size-4 animate-spin text-muted-foreground" />
      {:else}
        <Button size="sm" variant="default" class="h-7 px-2.5 text-xs" onclick={() => decide(approval, 'approve')}>
          <CheckIcon class="size-3" />
          <span class="ml-1">Approve</span>
        </Button>
        <Button size="sm" variant="outline" class="h-7 px-2.5 text-xs" onclick={() => decide(approval, 'deny')}>
          <XIcon class="size-3" />
          <span class="ml-1">Deny</span>
        </Button>
      {/if}
    </div>
  {/if}
{/each}
