import { writable, get } from "svelte/store";
import { invoke } from "@tauri-apps/api/core";

export interface PrdTask {
  id: string;
  title: string;
  prompt: string;
  priority: "high" | "medium" | "low";
  dependsOn?: string[];
}

export interface PrdFile {
  version: 1;
  goal: string;
  tasks: PrdTask[];
}

export const PRD_FILENAME = "hikari-tasks.json";

function buildPrdPrompt(userGoal: string, workingDirectory: string): string {
  return `Please create a PRD task breakdown for the following goal and write it as \`hikari-tasks.json\` in the working directory.

Goal: ${userGoal}

Write the file to \`${workingDirectory}/hikari-tasks.json\` containing valid JSON in this exact format:
\`\`\`json
{
  "version": 1,
  "goal": "<the goal>",
  "tasks": [
    {
      "id": "task-1",
      "title": "<short descriptive title>",
      "prompt": "<detailed prompt that Claude Code can execute to complete this task>",
      "priority": "<high|medium|low>",
      "dependsOn": []
    }
  ]
}
\`\`\`

Guidelines:
- Break the goal into 3–10 concrete, actionable tasks
- Each task should be completable in a single Claude Code session
- Prompts should be specific and actionable, not vague
- Order tasks logically (dependencies first)
- Assign priority: high for critical path, medium for features, low for polish/cleanup
- Fill in \`dependsOn\` with IDs of tasks that must complete before this one (use \`[]\` if none)
- Write only the JSON file — no explanations needed`;
}

function createPrdStore() {
  const goal = writable<string>("");
  const tasks = writable<PrdTask[]>([]);
  const isGenerating = writable<boolean>(false);
  const isLoaded = writable<boolean>(false);
  const isLoading = writable<boolean>(false);
  const isSaving = writable<boolean>(false);
  let idCounter = 0;

  async function loadFromFile(workingDirectory: string): Promise<void> {
    isLoading.set(true);
    try {
      const path = `${workingDirectory}/${PRD_FILENAME}`;
      const content = await invoke<string>("read_file_content", { path });
      const data = JSON.parse(content) as PrdFile;
      goal.set(data.goal);
      tasks.set(data.tasks);
      isLoaded.set(true);
    } catch (error) {
      console.error("Failed to load PRD file:", error);
      isLoaded.set(false);
    } finally {
      isLoading.set(false);
    }
  }

  async function saveToFile(workingDirectory: string): Promise<boolean> {
    isSaving.set(true);
    try {
      const path = `${workingDirectory}/${PRD_FILENAME}`;
      const data: PrdFile = {
        version: 1,
        goal: get(goal),
        tasks: get(tasks),
      };
      await invoke("write_file_content", { path, content: JSON.stringify(data, null, 2) });
      return true;
    } catch (error) {
      console.error("Failed to save PRD file:", error);
      return false;
    } finally {
      isSaving.set(false);
    }
  }

  async function generatePrd(
    userGoal: string,
    workingDirectory: string,
    conversationId: string
  ): Promise<void> {
    isGenerating.set(true);
    goal.set(userGoal);
    try {
      const prompt = buildPrdPrompt(userGoal, workingDirectory);
      await invoke("send_prompt", { conversationId, message: prompt });
    } catch (error) {
      console.error("Failed to generate PRD:", error);
      isGenerating.set(false);
    }
  }

  function finishGenerating(): void {
    isGenerating.set(false);
  }

  async function executePrd(workingDirectory: string, conversationId: string): Promise<void> {
    await saveToFile(workingDirectory);
    const currentTasks = get(tasks);
    const currentGoal = get(goal);
    const taskList = currentTasks
      .map((t, i) => `${i + 1}. [${t.priority}] **${t.title}**\n   ${t.prompt}`)
      .join("\n\n");
    const prompt = `Please execute the following task list for the goal: "${currentGoal}"

Work through each task in order, completing it fully before moving to the next:

${taskList}

The task list is also saved in \`${workingDirectory}/hikari-tasks.json\` for reference.`;
    await invoke("send_prompt", { conversationId, message: prompt });
  }

  function addTask(task: Omit<PrdTask, "id">): void {
    idCounter += 1;
    const id = `task-${idCounter}`;
    tasks.update((current) => [...current, { ...task, id }]);
  }

  function updateTask(id: string, changes: Partial<Omit<PrdTask, "id">>): void {
    tasks.update((current) => current.map((t) => (t.id === id ? { ...t, ...changes } : t)));
  }

  function removeTask(id: string): void {
    tasks.update((current) => current.filter((t) => t.id !== id));
  }

  function moveTaskUp(id: string): void {
    tasks.update((current) => {
      const index = current.findIndex((t) => t.id === id);
      if (index <= 0) return current;
      const result = [...current];
      [result[index - 1], result[index]] = [result[index], result[index - 1]];
      return result;
    });
  }

  function moveTaskDown(id: string): void {
    tasks.update((current) => {
      const index = current.findIndex((t) => t.id === id);
      if (index < 0 || index >= current.length - 1) return current;
      const result = [...current];
      [result[index], result[index + 1]] = [result[index + 1], result[index]];
      return result;
    });
  }

  function reset(): void {
    goal.set("");
    tasks.set([]);
    isLoaded.set(false);
    isGenerating.set(false);
    idCounter = 0;
  }

  return {
    goal: { subscribe: goal.subscribe },
    tasks: { subscribe: tasks.subscribe },
    isGenerating: { subscribe: isGenerating.subscribe },
    isLoaded: { subscribe: isLoaded.subscribe },
    isLoading: { subscribe: isLoading.subscribe },
    isSaving: { subscribe: isSaving.subscribe },
    loadFromFile,
    saveToFile,
    generatePrd,
    finishGenerating,
    executePrd,
    addTask,
    updateTask,
    removeTask,
    moveTaskUp,
    moveTaskDown,
    reset,
  };
}

export const prdStore = createPrdStore();
