import { ref } from "vue";
import { defineStore } from "pinia";
import { apiGet, apiPost, apiPut, apiDelete } from "@/api/client";
import { useToastStore } from "@/stores/toast";
import type { Note, NoteListResponse } from "@/types/note";

export const useNotesStore = defineStore("notes", () => {
  const notes = ref<Note[]>([]);
  const currentNote = ref<Note | null>(null);
  const total = ref(0);
  const loading = ref(false);

  // Filter / pagination / sort state
  const activeTagFilters = ref<string[]>([]);
  const limit = ref(20);
  const offset = ref(0);
  const sortField = ref("updated_at");
  const sortOrder = ref<"asc" | "desc">("desc");
  const searchQuery = ref("");

  async function refresh() {
    loading.value = true;
    try {
      const searchParams = new URLSearchParams();
      if (searchQuery.value) searchParams.set("q", searchQuery.value);
      for (const t of activeTagFilters.value) {
        searchParams.append("tag", t);
      }
      searchParams.set("sort", sortField.value);
      searchParams.set("order", sortOrder.value);
      searchParams.set("limit", String(limit.value));
      searchParams.set("offset", String(offset.value));

      const qs = searchParams.toString();
      const data = await apiGet<NoteListResponse>(
        `/api/notes${qs ? `?${qs}` : ""}`
      );
      notes.value = data.notes;
      total.value = data.total;
    } catch (e) {
      useToastStore().show("Failed to load notes", "error");
      throw e;
    } finally {
      loading.value = false;
    }
  }

  async function fetchNotes(params?: {
    q?: string;
    tag?: string[];
    sort?: string;
    order?: string;
    limit?: number;
    offset?: number;
  }) {
    if (params?.q !== undefined) searchQuery.value = params.q || "";
    if (params?.tag) activeTagFilters.value = params.tag;
    if (params?.sort) sortField.value = params.sort;
    if (params?.order) sortOrder.value = params.order as "asc" | "desc";
    if (params?.limit) limit.value = params.limit;
    if (params?.offset !== undefined) offset.value = params.offset;
    await refresh();
  }

  async function fetchNote(id: number) {
    loading.value = true;
    try {
      currentNote.value = await apiGet<Note>(`/api/notes/${id}`);
    } catch (e) {
      useToastStore().show("Failed to load note", "error");
      throw e;
    } finally {
      loading.value = false;
    }
  }

  async function createNote(data: {
    title: string;
    body: string;
    tags?: string[];
    project_id?: number | null;
    milestone_id?: number | null;
    note_type?: string;
    metadata?: Record<string, string> | null;
  }): Promise<Note> {
    try {
      return await apiPost<Note>("/api/notes", data);
    } catch (e) {
      useToastStore().show("Failed to create note", "error");
      throw e;
    }
  }

  async function updateNote(
    id: number,
    data: Partial<Pick<Note, "title" | "body" | "tags" | "project_id" | "milestone_id" | "note_type" | "metadata">>
  ): Promise<Note> {
    try {
      const note = await apiPut<Note>(`/api/notes/${id}`, data);
      if (currentNote.value?.id === id) {
        currentNote.value = note;
      }
      return note;
    } catch (e) {
      useToastStore().show("Failed to update note", "error");
      throw e;
    }
  }

  async function deleteNote(id: number) {
    try {
      await apiDelete(`/api/notes/${id}`);
      notes.value = notes.value.filter((n) => n.id !== id);
      if (currentNote.value?.id === id) {
        currentNote.value = null;
      }
    } catch (e) {
      useToastStore().show("Failed to delete note", "error");
      throw e;
    }
  }

  function addTagFilter(tag: string) {
    if (!activeTagFilters.value.includes(tag)) {
      activeTagFilters.value.push(tag);
      offset.value = 0;
      refresh();
    }
  }

  function removeTagFilter(tag: string) {
    activeTagFilters.value = activeTagFilters.value.filter((t) => t !== tag);
    offset.value = 0;
    refresh();
  }

  function clearTagFilters() {
    activeTagFilters.value = [];
    offset.value = 0;
    refresh();
  }

  function setTagFilters(tags: string[]) {
    activeTagFilters.value = [...tags];
    offset.value = 0;
    refresh();
  }

  function setSort(field: string, order: "asc" | "desc") {
    sortField.value = field;
    sortOrder.value = order;
    offset.value = 0;
    refresh();
  }

  function setOffset(newOffset: number) {
    offset.value = newOffset;
    refresh();
  }

  function setSearch(q: string) {
    searchQuery.value = q;
    offset.value = 0;
    refresh();
  }

  async function resolveTitle(title: string): Promise<Note> {
    return await apiPost<Note>("/api/notes/resolve-title", { title });
  }

  async function convertToTask(noteId: number): Promise<Note> {
    try {
      const note = await apiPost<Note>(
        `/api/notes/${noteId}/convert-to-task`,
        {}
      );
      if (currentNote.value?.id === noteId) {
        currentNote.value = note;
      }
      return note;
    } catch (e) {
      useToastStore().show("Failed to convert to task", "error");
      throw e;
    }
  }

  async function convertToNote(noteId: number): Promise<Note> {
    try {
      const note = await apiPost<Note>(
        `/api/notes/${noteId}/convert-to-note`,
        {}
      );
      if (currentNote.value?.id === noteId) {
        currentNote.value = note;
      }
      return note;
    } catch (e) {
      useToastStore().show("Failed to convert to note", "error");
      throw e;
    }
  }

  async function fetchBacklinks(
    noteId: number
  ): Promise<{ type: string; id: number; title: string }[]> {
    const data = await apiGet<{
      backlinks: { type: string; id: number; title: string }[];
    }>(`/api/notes/${noteId}/backlinks`);
    return data.backlinks;
  }

  async function fetchAllTags(q?: string): Promise<string[]> {
    const params = q ? `?q=${encodeURIComponent(q)}` : "";
    const data = await apiGet<{ tags: string[] }>(`/api/notes/tags${params}`);
    return data.tags;
  }

  return {
    notes,
    currentNote,
    total,
    loading,
    activeTagFilters,
    limit,
    offset,
    sortField,
    sortOrder,
    searchQuery,
    fetchNotes,
    fetchNote,
    createNote,
    updateNote,
    deleteNote,
    addTagFilter,
    removeTagFilter,
    clearTagFilters,
    setTagFilters,
    setSort,
    setOffset,
    setSearch,
    refresh,
    resolveTitle,
    convertToTask,
    convertToNote,
    fetchBacklinks,
    fetchAllTags,
  };
});
