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

export interface Snippet {
  id: string;
  name: string;
  content: string;
  category: string;
  is_default: boolean;
  created_at: string;
  updated_at: string;
}

function createSnippetsStore() {
  const snippets = writable<Snippet[]>([]);
  const categories = writable<string[]>([]);
  const isLoading = writable(false);
  const selectedCategory = writable<string | null>(null);

  const filteredSnippets = derived(
    [snippets, selectedCategory],
    ([$snippets, $selectedCategory]) => {
      if (!$selectedCategory) {
        return $snippets;
      }
      return $snippets.filter((s) => s.category === $selectedCategory);
    }
  );

  async function loadSnippets(): Promise<void> {
    isLoading.set(true);
    try {
      const [snippetList, categoryList] = await Promise.all([
        invoke<Snippet[]>("list_snippets"),
        invoke<string[]>("get_snippet_categories"),
      ]);
      snippets.set(snippetList);
      categories.set(categoryList);
    } catch (error) {
      console.error("Failed to load snippets:", error);
    } finally {
      isLoading.set(false);
    }
  }

  async function saveSnippet(snippet: Snippet): Promise<boolean> {
    try {
      await invoke("save_snippet", { snippet });
      await loadSnippets();
      return true;
    } catch (error) {
      console.error("Failed to save snippet:", error);
      return false;
    }
  }

  async function createSnippet(name: string, content: string, category: string): Promise<boolean> {
    const now = new Date().toISOString();
    const snippet: Snippet = {
      id: `custom-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
      name,
      content,
      category,
      is_default: false,
      created_at: now,
      updated_at: now,
    };
    return saveSnippet(snippet);
  }

  async function updateSnippet(
    id: string,
    name: string,
    content: string,
    category: string
  ): Promise<boolean> {
    const currentSnippets = await invoke<Snippet[]>("list_snippets");
    const existing = currentSnippets.find((s) => s.id === id);

    if (!existing) {
      console.error("Snippet not found for update");
      return false;
    }

    const updated: Snippet = {
      ...existing,
      name,
      content,
      category,
      updated_at: new Date().toISOString(),
    };

    return saveSnippet(updated);
  }

  async function deleteSnippet(snippetId: string): Promise<boolean> {
    try {
      await invoke("delete_snippet", { snippetId });
      await loadSnippets();
      return true;
    } catch (error) {
      console.error("Failed to delete snippet:", error);
      return false;
    }
  }

  async function resetDefaults(): Promise<boolean> {
    try {
      await invoke("reset_default_snippets");
      await loadSnippets();
      return true;
    } catch (error) {
      console.error("Failed to reset default snippets:", error);
      return false;
    }
  }

  function setSelectedCategory(category: string | null): void {
    selectedCategory.set(category);
  }

  return {
    snippets: { subscribe: snippets.subscribe },
    categories: { subscribe: categories.subscribe },
    filteredSnippets: { subscribe: filteredSnippets.subscribe },
    isLoading: { subscribe: isLoading.subscribe },
    selectedCategory: { subscribe: selectedCategory.subscribe },
    loadSnippets,
    saveSnippet,
    createSnippet,
    updateSnippet,
    deleteSnippet,
    resetDefaults,
    setSelectedCategory,
  };
}

export const snippetsStore = createSnippetsStore();
