<template>
  <div
    class="flex flex-col h-full bg-[#0d1117] border-l border-[#30363d] overflow-hidden"
    :style="{ width: panelWidth + 'px' }"
  >
    <!-- Header -->
    <div class="flex items-center justify-between px-3 py-2 bg-[#161b22] border-b border-[#30363d] shrink-0">
      <div class="flex items-center gap-2">
        <!-- Ghost icon -->
        <span class="text-base" title="XO AI Copilot">{{ ghostIcon }}</span>
        <span class="text-sm font-bold text-[#58a6ff]">XO</span>
        <span class="text-[10px] text-[#484f58]">{{ modelShort }}</span>
      </div>
      <div class="flex items-center gap-2">
        <!-- Token counter -->
        <span class="text-[10px] text-[#484f58]">
          {{ formatTokens(store.tokenUsage.input) }} / {{ formatTokens(store.tokenUsage.output) }}
        </span>
        <!-- Settings button -->
        <button
          class="text-[#8b949e] hover:text-[#e0e0e0] transition-colors cursor-pointer"
          title="Settings"
          @click="store.showSettings = true"
        >
          <svg class="w-3.5 h-3.5" viewBox="0 0 16 16" fill="currentColor">
            <path fill-rule="evenodd" d="M7.429 1.525a6.593 6.593 0 011.142 0c.036.003.108.036.137.146l.289 1.105c.147.56.55.967.997 1.189.174.086.341.183.501.29.417.278.97.423 1.53.27l1.102-.303c.11-.03.175.016.195.046.219.31.41.641.573.989.014.031.022.11-.059.19l-.815.806c-.411.406-.562.957-.53 1.456a4.588 4.588 0 010 .582c-.032.499.119 1.05.53 1.456l.815.806c.08.08.073.159.059.19a6.494 6.494 0 01-.573.99c-.02.029-.086.074-.195.045l-1.103-.303c-.559-.153-1.112-.008-1.529.27-.16.107-.327.204-.5.29-.449.222-.851.628-.998 1.189l-.289 1.105c-.029.11-.101.143-.137.146a6.613 6.613 0 01-1.142 0c-.036-.003-.108-.037-.137-.146l-.289-1.105c-.147-.56-.55-.967-.997-1.189a4.502 4.502 0 01-.501-.29c-.417-.278-.97-.423-1.53-.27l-1.102.303c-.11.03-.175-.016-.195-.046a6.492 6.492 0 01-.573-.989c-.014-.031-.022-.11.059-.19l.815-.806c.411-.406.562-.957.53-1.456a4.587 4.587 0 010-.582c.032-.499-.119-1.05-.53-1.456l-.815-.806c-.08-.08-.073-.159-.059-.19a6.44 6.44 0 01.573-.99c.02-.029.086-.074.195-.045l1.103.303c.559.153 1.112.008 1.529-.27.16-.107.327-.204.5-.29.449-.222.851-.628.998-1.189l.289-1.105c.029-.11.101-.143.137-.146zM8 0c-.236 0-.47.01-.701.03-.743.065-1.29.615-1.458 1.261l-.29 1.106c-.017.066-.078.158-.211.224a5.994 5.994 0 00-.668.386c-.123.082-.233.117-.3.1L3.27 2.801c-.635-.175-1.322.017-1.768.681A7.963 7.963 0 00.767 4.905c-.324.627-.2 1.358.246 1.8l.816.806c.049.048.098.153.088.313a6.088 6.088 0 000 .352c.01.16-.04.265-.088.313l-.816.806c-.446.443-.57 1.173-.246 1.8a7.96 7.96 0 00.736 1.323c.446.664 1.133.856 1.768.681l1.103-.303c.066-.018.177.018.3.1.22.147.447.28.668.386.133.066.194.158.212.224l.289 1.106c.169.646.715 1.196 1.458 1.26a8.094 8.094 0 001.402 0c.743-.064 1.29-.614 1.458-1.26l.29-1.106c.017-.066.078-.158.211-.224a5.98 5.98 0 00.668-.386c.123-.082.233-.117.3-.1l1.102.302c.635.175 1.322-.017 1.768-.68a7.96 7.96 0 00.736-1.324c.324-.627.2-1.357-.246-1.8l-.816-.805c-.048-.048-.098-.153-.088-.313a6.15 6.15 0 000-.352c-.01-.16.04-.265.088-.313l.816-.806c.446-.443.57-1.173.246-1.8a7.963 7.963 0 00-.736-1.323c-.446-.664-1.133-.856-1.768-.681l-1.103.303c-.066.018-.176-.018-.3-.1a5.99 5.99 0 00-.667-.386c-.133-.066-.194-.158-.212-.224L10.16 1.29C9.99.645 9.444.095 8.701.031A8.094 8.094 0 008 0zm1.5 8a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zM11 8a3 3 0 11-6 0 3 3 0 016 0z" />
          </svg>
        </button>
        <!-- Close button -->
        <button
          class="text-[#8b949e] hover:text-[#e0e0e0] transition-colors cursor-pointer"
          title="Close panel (Ctrl+Shift+K)"
          @click="store.togglePanel()"
        >
          <svg class="w-3.5 h-3.5" viewBox="0 0 16 16" fill="currentColor">
            <path d="M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z" />
          </svg>
        </button>
      </div>
    </div>

    <!-- Unauthenticated state -->
    <div
      v-if="!store.isAuthenticated"
      class="flex-1 flex flex-col items-center justify-center px-6"
    >
      <span class="text-4xl mb-4">{{ ghostIcon }}</span>
      <p class="text-sm text-[#8b949e] text-center mb-4">
        Connect to Claude to activate the XO AI copilot.
      </p>
      <button
        class="px-4 py-2 text-sm font-medium text-white bg-[#1f6feb] hover:bg-[#388bfd] rounded transition-colors cursor-pointer"
        @click="handleConnectLogin"
      >
        Connect to Claude
      </button>
    </div>

    <!-- Message list -->
    <div
      v-else
      ref="messageListRef"
      class="flex-1 overflow-y-auto px-3 py-3"
    >
      <!-- Empty state -->
      <div
        v-if="store.messages.length === 0"
        class="flex flex-col items-center justify-center h-full text-center"
      >
        <span class="text-3xl mb-3 opacity-40">{{ ghostIcon }}</span>
        <p class="text-sm text-[#8b949e]">XO standing by.</p>
        <p class="text-xs text-[#484f58] mt-1">Send a message to begin.</p>
      </div>

      <!-- Messages -->
      <CopilotMessage
        v-for="msg in store.messages"
        :key="msg.id"
        :message="msg"
        :is-streaming="store.isStreaming && msg.id === lastAssistantId"
      />
    </div>

    <!-- Input area (authenticated only) -->
    <div
      v-if="store.isAuthenticated"
      class="shrink-0 border-t border-[#30363d] p-3 bg-[#161b22]"
    >
      <div class="flex gap-2">
        <textarea
          ref="inputRef"
          v-model="inputText"
          :disabled="store.isStreaming"
          placeholder="Message the XO..."
          rows="1"
          class="flex-1 resize-none px-2.5 py-1.5 text-sm rounded bg-[#161b22] border border-[#30363d] text-[#e0e0e0] placeholder-[#484f58] outline-none focus:border-[#58a6ff] transition-colors disabled:opacity-50"
          @keydown="handleInputKeydown"
          @input="autoResize"
        />
        <button
          class="shrink-0 px-2.5 py-1.5 rounded transition-colors cursor-pointer"
          :class="
            canSend
              ? 'bg-[#1f6feb] hover:bg-[#388bfd] text-white'
              : 'bg-[#21262d] text-[#484f58] cursor-not-allowed'
          "
          :disabled="!canSend"
          title="Send message"
          @click="handleSend"
        >
          <svg class="w-4 h-4" viewBox="0 0 16 16" fill="currentColor">
            <path d="M.989 8 .064 2.68a1.342 1.342 0 0 1 1.85-1.462l13.402 5.744a1.13 1.13 0 0 1 0 2.076L1.913 14.782a1.343 1.343 0 0 1-1.85-1.463L.99 8Zm.603-5.108L2.18 7.25h4.57a.75.75 0 0 1 0 1.5H2.18l-.588 4.358L14.233 8 1.592 2.892Z" />
          </svg>
        </button>
      </div>
      <!-- Streaming indicator -->
      <div v-if="store.isStreaming" class="flex items-center gap-1.5 mt-1.5 text-[10px] text-[#3fb950]">
        <span class="w-1.5 h-1.5 rounded-full bg-[#3fb950] animate-pulse" />
        XO is responding...
      </div>
    </div>

    <!-- Settings modal -->
    <CopilotSettings v-if="store.showSettings" @close="store.showSettings = false" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted } from "vue";
import { useCopilotStore } from "@/stores/copilot.store";
import { useCopilot } from "@/composables/useCopilot";
import CopilotMessage from "./CopilotMessage.vue";
import CopilotSettings from "./CopilotSettings.vue";

const store = useCopilotStore();
const { processMessage, checkAuth, startLogin, getModel } = useCopilot();

// Check auth status and load model on mount
onMounted(async () => {
  await checkAuth();
  await getModel();
});

const panelWidth = 320;
const inputText = ref("");
const inputRef = ref<HTMLTextAreaElement | null>(null);
const messageListRef = ref<HTMLDivElement | null>(null);

/** Short model name for header display. */
const modelShort = computed(() => {
  const m = store.model;
  if (m.includes("sonnet")) return "sonnet";
  if (m.includes("opus")) return "opus";
  if (m.includes("haiku")) return "haiku";
  return m;
});

/** Trigger OAuth login from the inline panel button. */
async function handleConnectLogin(): Promise<void> {
  await startLogin();
  store.isAuthenticated = true;
}

/** Token formatter. */
function formatTokens(n: number): string {
  if (n >= 1000) return (n / 1000).toFixed(1) + "K";
  return String(n);
}

/** ID of the last assistant message (for streaming cursor). */
const lastAssistantId = computed(() => {
  for (let i = store.messages.length - 1; i >= 0; i--) {
    if (store.messages[i].role === "assistant") return store.messages[i].id;
  }
  return null;
});

/** Whether the send button should be active. */
const canSend = computed(() => inputText.value.trim().length > 0 && !store.isStreaming);

/** Send the message. */
async function handleSend(): Promise<void> {
  const text = inputText.value.trim();
  if (!text || store.isStreaming) return;

  inputText.value = "";
  resetTextareaHeight();

  store.sendMessage(text);
  await nextTick();
  scrollToBottom();

  await processMessage(text);
}

/** Handle keyboard shortcuts in the input area. */
function handleInputKeydown(event: KeyboardEvent): void {
  if (event.key === "Enter" && !event.shiftKey) {
    event.preventDefault();
    handleSend();
  }
}

/** Auto-resize textarea based on content. */
function autoResize(): void {
  const el = inputRef.value;
  if (!el) return;
  el.style.height = "auto";
  el.style.height = Math.min(el.scrollHeight, 120) + "px";
}

/** Reset textarea height back to single line. */
function resetTextareaHeight(): void {
  const el = inputRef.value;
  if (!el) return;
  el.style.height = "auto";
}

/** Scroll the message list to the bottom. */
function scrollToBottom(): void {
  const el = messageListRef.value;
  if (!el) return;
  el.scrollTop = el.scrollHeight;
}

/** Auto-scroll when messages change or streaming content updates. */
watch(
  () => store.messages.length,
  async () => {
    await nextTick();
    scrollToBottom();
  },
);

watch(
  () => {
    const msgs = store.messages;
    if (msgs.length === 0) return "";
    return msgs[msgs.length - 1].content;
  },
  async () => {
    await nextTick();
    scrollToBottom();
  },
);

// The ghost icon used in multiple places
const ghostIcon = "\uD83D\uDC7B";
</script>
