<template>
  <div class="flex h-full relative">
    <!-- Drag handle for resizing -->
    <div
      class="w-1 cursor-col-resize hover:bg-[var(--wraith-accent-blue)] active:bg-[var(--wraith-accent-blue)] transition-colors shrink-0"
      @pointerdown="startResize"
    />
    <div
      class="flex flex-col h-full bg-[var(--wraith-bg-secondary)] border-l border-[var(--wraith-border)] flex-1 min-w-0"
      :style="{ width: panelWidth + 'px' }"
    >
    <!-- Header -->
    <div class="p-3 border-b border-[var(--wraith-border)] flex items-center justify-between gap-2">
      <span class="text-xs font-bold tracking-widest text-[var(--wraith-accent-blue)]">AI COPILOT</span>
      <div class="flex items-center gap-1.5">
        <select
          v-model="selectedShell"
          class="bg-[var(--wraith-bg-tertiary)] border border-[var(--wraith-border)] rounded px-1.5 py-0.5 text-[10px] text-[var(--wraith-text-secondary)] outline-none"
          :disabled="connected"
        >
          <option v-for="shell in shells" :key="shell.path" :value="shell.path">
            {{ shell.name }}
          </option>
        </select>
        <button
          v-if="!connected"
          class="px-2 py-0.5 text-[10px] font-bold rounded bg-[var(--wraith-accent-blue)] text-black cursor-pointer"
          :disabled="!selectedShell"
          @click="launch"
        >
          Launch
        </button>
        <button
          v-else
          class="px-2 py-0.5 text-[10px] font-bold rounded bg-[var(--wraith-accent-red,#f85149)] text-white cursor-pointer"
          @click="kill"
        >
          Kill
        </button>
      </div>
    </div>

    <!-- Terminal area -->
    <div v-if="connected" ref="containerRef" class="flex-1 min-h-0" />

    <!-- Session ended prompt -->
    <div v-else-if="sessionEnded" class="flex-1 flex flex-col items-center justify-center gap-3 p-4">
      <p class="text-xs text-[var(--wraith-text-muted)]">Session ended</p>
      <button
        class="px-3 py-1.5 text-xs rounded bg-[var(--wraith-accent-blue)] text-black font-bold cursor-pointer"
        @click="launch"
      >
        Relaunch
      </button>
    </div>

    <!-- Empty state with quick-launch presets -->
    <div v-else class="flex-1 flex flex-col items-center justify-center gap-3 p-4">
      <p class="text-xs text-[var(--wraith-text-muted)] text-center">
        Select a shell and click Launch, or use a preset:
      </p>
      <div v-if="presets.length" class="flex flex-col gap-1.5 w-full max-w-[200px]">
        <button
          v-for="preset in presets"
          :key="preset.name"
          class="px-3 py-1.5 text-xs rounded bg-[var(--wraith-bg-tertiary)] border border-[var(--wraith-border)] text-[var(--wraith-text-secondary)] hover:text-[var(--wraith-text-primary)] hover:border-[var(--wraith-accent-blue)] transition-colors cursor-pointer text-left"
          @click="launchPreset(preset)"
        >
          {{ preset.name }}
        </button>
      </div>
      <p class="text-[10px] text-[var(--wraith-text-muted)] text-center">
        Configure presets in Settings → AI Copilot
      </p>
    </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, nextTick, onMounted, onBeforeUnmount } from "vue";
import { invoke } from "@tauri-apps/api/core";
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
import { useTerminal } from "@/composables/useTerminal";

interface ShellInfo { name: string; path: string; }

// Resizable panel
const panelWidth = ref(640);

function startResize(e: PointerEvent): void {
  e.preventDefault();
  const startX = e.clientX;
  const startWidth = panelWidth.value;

  function onMove(ev: PointerEvent): void {
    // Dragging left increases width (panel is on the right side)
    const delta = startX - ev.clientX;
    panelWidth.value = Math.max(320, Math.min(1200, startWidth + delta));
  }

  function onUp(): void {
    document.removeEventListener("pointermove", onMove);
    document.removeEventListener("pointerup", onUp);
  }

  document.addEventListener("pointermove", onMove);
  document.addEventListener("pointerup", onUp);
}

interface LaunchPreset { name: string; shell: string; command: string; }

const presets = ref<LaunchPreset[]>([]);

const shells = ref<ShellInfo[]>([]);
const selectedShell = ref("");
const connected = ref(false);
const sessionEnded = ref(false);
const containerRef = ref<HTMLElement | null>(null);

let sessionId = "";
let terminalInstance: ReturnType<typeof useTerminal> | null = null;
let closeUnlisten: UnlistenFn | null = null;

async function loadShells(): Promise<void> {
  try {
    shells.value = await invoke<ShellInfo[]>("list_available_shells");
    if (shells.value.length > 0 && !selectedShell.value) {
      selectedShell.value = shells.value[0].path;
    }
  } catch (err) {
    console.error("Failed to list shells:", err);
  }
}

async function loadPresets(): Promise<void> {
  try {
    const raw = await invoke<string | null>("get_setting", { key: "copilot_presets" });
    if (raw) {
      presets.value = JSON.parse(raw);
    } else {
      // Seed with sensible defaults
      presets.value = [
        { name: "Claude Code", shell: "", command: "claude" },
        { name: "Gemini CLI", shell: "", command: "gemini" },
        { name: "Codex CLI", shell: "", command: "codex" },
      ];
    }
  } catch {
    presets.value = [];
  }
}

async function launchPreset(preset: LaunchPreset): Promise<void> {
  const shell = preset.shell || selectedShell.value;
  if (!shell) return;
  selectedShell.value = shell;
  await launch();
  // Wait for the shell prompt before sending the command.
  // Poll the scrollback for a prompt indicator (PS>, $, #, %, >)
  if (sessionId && connected.value) {
    const maxWait = 5000;
    const start = Date.now();
    const poll = setInterval(async () => {
      if (Date.now() - start > maxWait) {
        clearInterval(poll);
        // Send anyway after timeout
        invoke("pty_write", { sessionId, data: preset.command + "\r" }).catch(() => {});
        return;
      }
      try {
        const lines = await invoke<string>("mcp_terminal_read", { sessionId, lines: 3 });
        const lastLine = lines.split("\n").pop()?.trim() || "";
        // Detect common shell prompts
        if (lastLine.endsWith("$") || lastLine.endsWith("#") || lastLine.endsWith("%") || lastLine.endsWith(">") || lastLine.endsWith("PS>")) {
          clearInterval(poll);
          invoke("pty_write", { sessionId, data: preset.command + "\r" }).catch(() => {});
        }
      } catch {
        // Scrollback not ready yet, keep polling
      }
    }, 200);
  }
}

async function launch(): Promise<void> {
  if (!selectedShell.value) return;
  sessionEnded.value = false;

  try {
    sessionId = await invoke<string>("spawn_local_shell", {
      shellPath: selectedShell.value,
      cols: 80,
      rows: 24,
    });
    connected.value = true;

    await nextTick();

    if (containerRef.value) {
      terminalInstance = useTerminal(sessionId, "pty");
      terminalInstance.mount(containerRef.value);

      // Fit after mount to get real dimensions, then resize the PTY
      setTimeout(() => {
        if (terminalInstance) {
          terminalInstance.fit();
          const term = terminalInstance.terminal;
          invoke("pty_resize", {
            sessionId,
            cols: term.cols,
            rows: term.rows,
          }).catch(() => {});
        }
      }, 50);
    }

    // Listen for shell exit
    closeUnlisten = await listen(`pty:close:${sessionId}`, () => {
      cleanup();
      sessionEnded.value = true;
    });
  } catch (err) {
    console.error("Failed to spawn shell:", err);
    connected.value = false;
  }
}

function kill(): void {
  if (sessionId) {
    invoke("disconnect_pty", { sessionId }).catch(() => {});
  }
  cleanup();
}

function cleanup(): void {
  if (terminalInstance) {
    terminalInstance.destroy();
    terminalInstance = null;
  }
  if (closeUnlisten) {
    closeUnlisten();
    closeUnlisten = null;
  }
  connected.value = false;
  sessionId = "";
}

onMounted(() => {
  loadShells();
  loadPresets();
});

onBeforeUnmount(() => {
  if (connected.value) kill();
});
</script>
