import { get } from "svelte/store";
import { invoke } from "@tauri-apps/api/core";
import { claudeStore } from "$lib/stores/claude";
import { characterState } from "$lib/stores/character";
import { setSkipNextGreeting } from "$lib/tauri";
import { searchState } from "$lib/stores/search";

export interface SlashCommand {
  name: string;
  description: string;
  usage: string;
  execute: (args: string) => Promise<void> | void;
}

async function changeDirectory(path: string): Promise<void> {
  const conversationId = get(claudeStore.activeConversationId);
  if (!conversationId) {
    claudeStore.addLine("error", "No active conversation");
    return;
  }

  if (!path.trim()) {
    const currentDir = get(claudeStore.currentWorkingDirectory);
    claudeStore.addLine("system", `Current directory: ${currentDir}`);
    return;
  }

  try {
    characterState.setState("thinking");
    claudeStore.addLine("system", `Changing directory to: ${path}`);

    const currentDir = get(claudeStore.currentWorkingDirectory);
    const validatedPath = await invoke<string>("validate_directory", { path, currentDir });

    // Capture conversation history before disconnecting
    const conversationHistory = claudeStore.getConversationHistory();

    await invoke("stop_claude", { conversationId });

    // Wait for clean shutdown
    await new Promise((resolve) => setTimeout(resolve, 500));

    claudeStore.setWorkingDirectory(validatedPath);

    setSkipNextGreeting(true);

    await invoke("start_claude", {
      conversationId,
      options: {
        working_dir: validatedPath,
      },
    });

    // Wait for connection to establish
    await new Promise((resolve) => setTimeout(resolve, 1000));

    // Restore context if there was conversation history
    if (conversationHistory) {
      const contextMessage = `[CONTEXT RESTORATION]
I just changed the working directory from ${currentDir} to ${validatedPath}. Here's our conversation so far:

${conversationHistory}

Please continue where we left off. You are now operating in the new directory.`;

      await invoke("send_prompt", {
        conversationId,
        message: contextMessage,
      });
    }

    claudeStore.addLine("system", `Changed directory to: ${validatedPath}`);
    characterState.setState("idle");
  } catch (error) {
    claudeStore.addLine("error", `Failed to change directory: ${error}`);
    characterState.setTemporaryState("error", 3000);
  }
}

async function startNewConversation(): Promise<void> {
  const conversationId = get(claudeStore.activeConversationId);
  if (!conversationId) {
    claudeStore.addLine("error", "No active conversation");
    return;
  }

  try {
    const workingDir = await invoke<string>("get_working_directory", {
      conversationId,
    });

    claudeStore.addLine("system", "Starting new conversation...");
    characterState.setState("thinking");

    await invoke("interrupt_claude", { conversationId });

    claudeStore.clearTerminal();

    setSkipNextGreeting(true);

    await invoke("start_claude", {
      conversationId,
      options: {
        working_dir: workingDir,
      },
    });

    claudeStore.addLine("system", "New conversation started!");
    characterState.setState("idle");
  } catch (error) {
    claudeStore.addLine("error", `Failed to start new conversation: ${error}`);
    characterState.setTemporaryState("error", 3000);
  }
}

export const slashCommands: SlashCommand[] = [
  {
    name: "cd",
    description: "Change the working directory",
    usage: "/cd <path>",
    execute: changeDirectory,
  },
  {
    name: "clear",
    description: "Clear the terminal display (keeps conversation context)",
    usage: "/clear",
    execute: () => {
      claudeStore.clearTerminal();
      claudeStore.addLine("system", "Terminal cleared");
    },
  },
  {
    name: "new",
    description: "Start a fresh conversation (resets context)",
    usage: "/new",
    execute: startNewConversation,
  },
  {
    name: "help",
    description: "Show available slash commands",
    usage: "/help",
    execute: () => {
      const helpText = slashCommands
        .map((cmd) => `  ${cmd.usage.padEnd(12)} - ${cmd.description}`)
        .join("\n");
      claudeStore.addLine("system", `Available commands:\n${helpText}`);
    },
  },
  {
    name: "search",
    description: "Search within the conversation (use /search to clear)",
    usage: "/search [query]",
    execute: (args: string) => {
      if (!args.trim()) {
        searchState.clear();
        claudeStore.addLine("system", "Search cleared");
        return;
      }
      searchState.setQuery(args.trim());
      claudeStore.addLine("system", `Searching for: "${args.trim()}"`);
    },
  },
  {
    name: "summarise",
    description: "Get a summary of the entire conversation",
    usage: "/summarise",
    execute: async () => {
      const conversationId = get(claudeStore.activeConversationId);
      if (!conversationId) {
        claudeStore.addLine("error", "No active conversation");
        return;
      }

      try {
        claudeStore.addLine("system", "Requesting conversation summary...");
        await invoke("send_prompt", {
          conversationId,
          message:
            "Please provide a comprehensive summary of our entire conversation so far, including the key topics we've discussed, decisions made, and any important context.",
        });
      } catch (error) {
        claudeStore.addLine("error", `Failed to request summary: ${error}`);
      }
    },
  },
  {
    name: "skill",
    description: "Invoke a Claude Code skill from ~/.claude/skills/",
    usage: "/skill [name] [data]",
    execute: async (args: string) => {
      const conversationId = get(claudeStore.activeConversationId);
      if (!conversationId) {
        claudeStore.addLine("error", "No active conversation");
        return;
      }

      const parts = args.trim().split(/\s+/);
      const skillName = parts[0];
      const skillData = parts.slice(1).join(" ");

      // If no skill name provided, list available skills
      if (!skillName) {
        try {
          const skills = await invoke<string[]>("list_skills");
          if (skills.length === 0) {
            claudeStore.addLine(
              "system",
              "No skills found in ~/.claude/skills/\nCreate a skill by adding a folder with a SKILL.md file."
            );
          } else {
            const skillList = skills.map((s) => `  • ${s}`).join("\n");
            claudeStore.addLine(
              "system",
              `Available skills:\n${skillList}\n\nUsage: /skill <skill-name> [data]`
            );
          }
        } catch (error) {
          claudeStore.addLine("error", `Failed to list skills: ${error}`);
        }
        return;
      }

      try {
        claudeStore.addLine("system", `Invoking skill: ${skillName}`);
        characterState.setState("thinking");

        const message = skillData
          ? `Please run the /${skillName} skill with the following data:\n\n${skillData}`
          : `Please run the /${skillName} skill.`;

        await invoke("send_prompt", {
          conversationId,
          message,
        });
      } catch (error) {
        claudeStore.addLine("error", `Failed to invoke skill: ${error}`);
        characterState.setTemporaryState("error", 3000);
      }
    },
  },
];

export function parseSlashCommand(input: string): {
  command: SlashCommand | null;
  args: string;
} {
  const trimmed = input.trim();

  if (!trimmed.startsWith("/")) {
    return { command: null, args: "" };
  }

  const parts = trimmed.slice(1).split(/\s+/);
  const commandName = parts[0]?.toLowerCase();
  const args = parts.slice(1).join(" ");

  const command = slashCommands.find((cmd) => cmd.name.toLowerCase() === commandName);

  return { command: command || null, args };
}

export function getMatchingCommands(input: string): SlashCommand[] {
  const trimmed = input.trim();

  if (!trimmed.startsWith("/")) {
    return [];
  }

  const partial = trimmed.slice(1).toLowerCase();

  if (partial === "") {
    return slashCommands;
  }

  return slashCommands.filter((cmd) => cmd.name.toLowerCase().startsWith(partial));
}

export function isSlashCommand(input: string): boolean {
  return input.trim().startsWith("/");
}
