<template>
  <div v-if="dialog" class="rounded-lg border border-amber-900/60 bg-amber-950/30 p-3">
    <div class="flex items-center gap-2">
      <span class="badge bg-amber-900 text-amber-200">{{ t(`sessions.dialog.kind.${dialog.kind}`) }}</span>
      <span class="text-sm text-amber-100">{{ dialog.waitingFor ?? t('sessions.dialog.waiting') }}</span>
    </div>
    <!-- Options empilées verticalement et pleine largeur : un libellé long (ex. AskUserQuestion) wrappe
         proprement au lieu d'être tronqué/collé au suivant comme avec un flex-wrap horizontal. -->
    <div class="mt-2 flex flex-col gap-1.5">
      <button
        v-for="opt in dialog.options"
        :key="opt.n"
        class="btn w-full items-start justify-start whitespace-normal break-words text-left text-xs"
        :class="opt.selected ? 'border-amber-400 text-amber-200' : ''"
        :disabled="busy"
        @click="respond('select', opt.n)"
      >
        <span class="font-mono text-amber-400">{{ opt.n }}</span>
        <span class="min-w-0 flex-1">{{ opt.label }}</span>
      </button>
      <button class="btn-danger w-full justify-start text-left text-xs" :disabled="busy" @click="respond('deny')">
        {{ t('sessions.dialog.deny') }}
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
// P4-A : répondre à un dialogue Claude sans ouvrir le terminal. Le composant gère sa
// propre attache interactive LÉGÈRE (sink no-op, sans xterm), créée à la demande au
// premier clic et libérée au démontage : c'est ce qui réalise la réponse « mobile ».
import { computed, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import type { SessionSummary } from '@arboretum/shared';
import { wsClient, type Attachment, type TerminalSink } from '../lib/ws-client';
import { ref } from 'vue';

const props = defineProps<{ session: SessionSummary }>();
const { t } = useI18n();

const busy = ref(false);
const dialog = computed(() => (props.session.activity === 'waiting' ? props.session.dialog ?? null : null));

// Sink no-op : l'attache de réponse n'affiche rien ; elle rappelle le callback du flow
// control pour ne jamais bloquer le PTY côté serveur.
const noopSink: TerminalSink = {
  write: (_data, cb) => cb?.(),
  reset: () => {},
  onDetached: () => {},
  onControlChanged: () => {},
};

let attachPromise: Promise<Attachment> | null = null;
function ensureAttached(): Promise<Attachment> {
  attachPromise ??= wsClient.attach({ sessionId: props.session.id, mode: 'interactive', cols: 120, rows: 32, sink: noopSink });
  return attachPromise;
}

async function respond(action: 'select' | 'confirm' | 'deny', optionN?: number): Promise<void> {
  busy.value = true;
  try {
    const att = await ensureAttached();
    att.answer(action, optionN);
  } catch {
    // attache impossible (session disparue) : l'état réel arrive par session_update
  } finally {
    busy.value = false;
  }
}

onUnmounted(() => {
  attachPromise?.then((a) => a.detach()).catch(() => {});
});
</script>
