<script lang="ts">
  import { invoke } from "@tauri-apps/api/core";
  import { get } from "svelte/store";
  import { claudeStore, isClaudeProcessing } from "$lib/stores/claude";
  import { characterState } from "$lib/stores/character";
  import { handleNewUserMessage } from "$lib/notifications/rules";
  import { setSkipNextGreeting } from "$lib/tauri";
  import {
    setShouldRestoreHistory,
    setSavedHistory,
    getShouldRestoreHistory,
    getSavedHistory,
    clearHistoryRestore,
  } from "$lib/stores/historyRestore";
  import MessageModeSelector from "$lib/components/MessageModeSelector.svelte";
  import SlashCommandMenu from "$lib/components/SlashCommandMenu.svelte";
  import { getCurrentMode } from "$lib/stores/messageMode";
  import { formatMessageWithMode } from "$lib/types/messageMode";
  import {
    parseSlashCommand,
    getMatchingCommands,
    isSlashCommand,
    type SlashCommand,
  } from "$lib/commands/slashCommands";

  const INPUT_HISTORY_KEY = "hikari-input-history";
  const MAX_HISTORY_SIZE = 100;

  let inputValue = $state("");
  let isSubmitting = $state(false);
  let isConnected = $state(false);
  let isProcessing = $state(false);
  let showCommandMenu = $state(false);
  let matchingCommands = $state<SlashCommand[]>([]);
  let selectedCommandIndex = $state(0);

  // Input history state
  let inputHistory = $state<string[]>([]);
  let historyIndex = $state(-1);
  let tempInput = $state("");

  // Textarea resize state
  let textareaHeight = $state(48);
  const MIN_HEIGHT = 48;
  const MAX_HEIGHT = 200;
  let isResizing = $state(false);
  let startY = 0;
  let startHeight = 0;

  function handleResizeStart(event: MouseEvent) {
    isResizing = true;
    startY = event.clientY;
    startHeight = textareaHeight;
    document.addEventListener("mousemove", handleResizeMove);
    document.addEventListener("mouseup", handleResizeEnd);
    event.preventDefault();
  }

  function handleResizeMove(event: MouseEvent) {
    if (!isResizing) return;
    // Dragging up (negative deltaY) should increase height
    const deltaY = startY - event.clientY;
    const newHeight = Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, startHeight + deltaY));
    textareaHeight = newHeight;
  }

  function handleResizeEnd() {
    isResizing = false;
    document.removeEventListener("mousemove", handleResizeMove);
    document.removeEventListener("mouseup", handleResizeEnd);
  }

  // Load history from localStorage on init
  function loadHistory(): string[] {
    try {
      const stored = localStorage.getItem(INPUT_HISTORY_KEY);
      return stored ? JSON.parse(stored) : [];
    } catch {
      return [];
    }
  }

  function saveHistory(history: string[]) {
    try {
      localStorage.setItem(INPUT_HISTORY_KEY, JSON.stringify(history));
    } catch {
      // Ignore storage errors
    }
  }

  function addToHistory(input: string) {
    const trimmed = input.trim();
    if (!trimmed) return;

    // Don't add duplicates of the most recent entry
    if (inputHistory.length > 0 && inputHistory[0] === trimmed) return;

    // Add to front of history
    inputHistory = [trimmed, ...inputHistory.slice(0, MAX_HISTORY_SIZE - 1)];
    saveHistory(inputHistory);
  }

  // Initialize history on mount
  inputHistory = loadHistory();

  claudeStore.connectionStatus.subscribe((status) => {
    isConnected = status === "connected";
  });

  isClaudeProcessing.subscribe((processing) => {
    isProcessing = processing;
  });

  function handleInputChange() {
    // Reset history navigation when user types
    historyIndex = -1;
    tempInput = "";

    if (isSlashCommand(inputValue)) {
      matchingCommands = getMatchingCommands(inputValue);
      showCommandMenu = matchingCommands.length > 0;
      selectedCommandIndex = 0;
    } else {
      showCommandMenu = false;
      matchingCommands = [];
    }
  }

  function selectCommand(command: SlashCommand) {
    inputValue = `/${command.name} `;
    showCommandMenu = false;
    matchingCommands = [];
  }

  async function executeSlashCommand(): Promise<boolean> {
    const { command, args } = parseSlashCommand(inputValue);
    if (command) {
      inputValue = "";
      showCommandMenu = false;
      matchingCommands = [];
      await command.execute(args);
      return true;
    }
    return false;
  }

  async function handleSubmit(event: Event) {
    event.preventDefault();

    const message = inputValue.trim();
    if (!message || isSubmitting) return;

    // Check for slash commands first (these work even when disconnected)
    if (isSlashCommand(message)) {
      // Add slash commands to history too
      addToHistory(message);
      historyIndex = -1;
      tempInput = "";

      const wasCommand = await executeSlashCommand();
      if (wasCommand) return;
      // If it started with / but wasn't a valid command, show error
      claudeStore.addLine(
        "error",
        `Unknown command: ${message.split(" ")[0]}. Type /help for available commands.`
      );
      inputValue = "";
      return;
    }

    // Regular messages require connection
    if (!isConnected) return;

    // Add to history before clearing
    addToHistory(message);
    historyIndex = -1;
    tempInput = "";

    isSubmitting = true;
    inputValue = "";

    // Apply mode prefix if needed
    const currentMode = getCurrentMode();
    const formattedMessage = formatMessageWithMode(message, currentMode);

    // Check if we need to restore conversation history
    let messageToSend = formattedMessage;
    if (getShouldRestoreHistory()) {
      const savedHistory = getSavedHistory();

      if (savedHistory) {
        // Prepend the conversation history with a context message
        messageToSend = `[Previous conversation context:]
${savedHistory}

[Continuing conversation after reconnection:]
User: ${formattedMessage}`;

        // Clear the restoration flags
        clearHistoryRestore();
      }
    }

    // Reset notification state for new user message
    handleNewUserMessage();

    claudeStore.addLine("user", formattedMessage);
    characterState.setState("thinking");

    try {
      const conversationId = get(claudeStore.activeConversationId);
      if (!conversationId) {
        throw new Error("No active conversation");
      }
      await invoke("send_prompt", {
        conversationId,
        message: messageToSend,
      });
    } catch (error) {
      console.error("Failed to send prompt:", error);
      claudeStore.addLine("error", `Failed to send: ${error}`);
      characterState.setTemporaryState("error", 3000);
    } finally {
      isSubmitting = false;
    }
  }

  async function handleInterrupt() {
    // Save the conversation history FIRST before anything else
    const history = claudeStore.getConversationHistory();

    if (history) {
      setSavedHistory(history);
      setShouldRestoreHistory(true);
    }

    try {
      const conversationId = get(claudeStore.activeConversationId);
      if (!conversationId) {
        throw new Error("No active conversation");
      }
      await invoke("interrupt_claude", { conversationId });
      claudeStore.addLine("system", "Process interrupted - reconnecting...");
      characterState.setState("idle");

      // Show connecting status while we reconnect
      claudeStore.setConnectionStatus("connecting");

      // Auto-reconnect after a brief delay
      setTimeout(async () => {
        try {
          const conversationId = get(claudeStore.activeConversationId);
          if (!conversationId) {
            throw new Error("No active conversation");
          }

          // Get current working directory before reconnecting
          const workingDir = await invoke<string>("get_working_directory", { conversationId });

          // Set the flag to skip greeting on next connection
          setSkipNextGreeting(true);

          // Reconnect to Claude
          await invoke("start_claude", {
            conversationId,
            options: {
              working_dir: workingDir,
            },
          });
        } catch (reconnectError) {
          console.error("Failed to auto-reconnect:", reconnectError);
          claudeStore.addLine("error", `Failed to reconnect: ${reconnectError}`);
          claudeStore.addLine("system", "Please manually reconnect to continue");
        }
      }, 500); // Brief delay to ensure process is fully terminated
    } catch (error) {
      console.error("Failed to interrupt:", error);
      claudeStore.addLine("error", `Failed to interrupt: ${error}`);
    }
  }

  function handleKeyDown(event: KeyboardEvent) {
    // Handle command menu navigation
    if (showCommandMenu && matchingCommands.length > 0) {
      if (event.key === "ArrowDown") {
        event.preventDefault();
        selectedCommandIndex = (selectedCommandIndex + 1) % matchingCommands.length;
        return;
      }
      if (event.key === "ArrowUp") {
        event.preventDefault();
        selectedCommandIndex =
          (selectedCommandIndex - 1 + matchingCommands.length) % matchingCommands.length;
        return;
      }
      if (event.key === "Tab") {
        event.preventDefault();
        const selected = matchingCommands[selectedCommandIndex];
        if (selected) {
          selectCommand(selected);
        }
        return;
      }
      if (event.key === "Escape") {
        event.preventDefault();
        showCommandMenu = false;
        return;
      }
    }

    // Handle input history navigation (when command menu is closed)
    if (event.key === "ArrowUp" && inputHistory.length > 0) {
      event.preventDefault();
      if (historyIndex === -1) {
        // Save current input before navigating history
        tempInput = inputValue;
      }
      if (historyIndex < inputHistory.length - 1) {
        historyIndex++;
        inputValue = inputHistory[historyIndex];
      }
      return;
    }

    if (event.key === "ArrowDown" && historyIndex >= 0) {
      event.preventDefault();
      historyIndex--;
      if (historyIndex === -1) {
        // Restore the temp input when going back to current
        inputValue = tempInput;
      } else {
        inputValue = inputHistory[historyIndex];
      }
      return;
    }

    if (event.key === "Enter" && !event.shiftKey) {
      handleSubmit(event);
    }
  }
</script>

<form onsubmit={handleSubmit} class="input-bar">
  <div class="input-controls flex gap-2 mb-2">
    <MessageModeSelector />
  </div>

  <div class="input-row">
    <div class="textarea-wrapper">
      <SlashCommandMenu
        commands={matchingCommands}
        selectedIndex={selectedCommandIndex}
        onSelect={selectCommand}
      />
      <!-- svelte-ignore a11y_no_static_element_interactions -->
      <div
        class="resize-handle"
        onmousedown={handleResizeStart}
        title="Drag to resize"
      ></div>
      <textarea
        bind:value={inputValue}
        onkeydown={handleKeyDown}
        oninput={handleInputChange}
        placeholder={isConnected
          ? "Ask Hikari anything... (type / for commands)"
          : "Connect to Claude first..."}
        disabled={isSubmitting}
        rows={1}
        style="height: {textareaHeight}px"
        class="w-full px-4 py-3 bg-[var(--bg-secondary)] border border-[var(--border-color)]
             rounded-lg text-[var(--text-primary)] placeholder-gray-500 resize-none
             focus:outline-none focus:border-[var(--accent-primary)] focus:ring-1 focus:ring-[var(--accent-primary)]
             disabled:opacity-50 disabled:cursor-not-allowed"
      ></textarea>
    </div>

    <div class="button-wrapper">
      {#if isProcessing}
        <button
          type="button"
          onclick={handleInterrupt}
          class="send-button bg-red-600 hover:bg-red-700"
          title="Interrupt the current response (Ctrl+C)"
        >
          <span class="font-bold">■</span> Stop
        </button>
      {:else}
        <button
          type="submit"
          disabled={!isConnected || isSubmitting || !inputValue.trim()}
          class="send-button bg-[var(--accent-primary)] hover:bg-[var(--accent-secondary)]
               disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {#if isSubmitting}
            <span class="inline-block animate-spin">⏳</span>
          {:else}
            Send
          {/if}
        </button>
      {/if}
    </div>
  </div>
</form>

<style>
  .input-bar {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .input-controls {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .input-row {
    display: flex;
    gap: 12px;
    align-items: flex-end;
  }

  .textarea-wrapper {
    flex: 1;
    position: relative;
    display: flex;
    flex-direction: column;
  }

  .resize-handle {
    height: 6px;
    cursor: ns-resize;
    background: transparent;
    border-radius: 3px;
    margin-bottom: 2px;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .resize-handle::before {
    content: "";
    width: 40px;
    height: 3px;
    background: var(--border-color);
    border-radius: 2px;
    opacity: 0.5;
    transition: opacity 0.2s;
  }

  .resize-handle:hover::before {
    opacity: 1;
    background: var(--accent-primary);
  }

  .button-wrapper {
    display: flex;
    align-items: flex-end;
    height: 100%;
  }

  .send-button {
    padding: 0 24px;
    height: 48px;
    color: white;
    font-weight: 500;
    border-radius: 8px;
    transition: all 0.2s;
    white-space: nowrap;
  }

  .send-button:hover:not(:disabled) {
    transform: scale(1.05);
  }

  .send-button:active:not(:disabled) {
    transform: scale(0.95);
  }
</style>
