import { create } from "zustand";
import type { NoteContent, NoteIndexItem } from "../api/notesApi";
import { createNote, deleteNote, fetchNote, fetchNotes, syncNote, updateNote } from "../api/notesApi";

type NotesState = {
  notes: NoteIndexItem[];
  activeId?: string;
  activeNote?: NoteContent;
  search: string;
  isLoading: boolean;
  isSaving: boolean;
  previewMode: boolean;
  error?: string;
  loadNotes: () => Promise<void>;
  selectNote: (id: string) => Promise<void>;
  createNew: () => Promise<void>;
  updateActive: (title: string, content: string) => void;
  saveActive: () => Promise<void>;
  removeActive: () => Promise<void>;
  removeById: (id: string) => Promise<void>;
  retrySync: () => Promise<void>;
  setSearch: (value: string) => void;
  togglePreview: () => void;
};

export const useNotesStore = create<NotesState>((set, get) => ({
  notes: [],
  search: "",
  isLoading: false,
  isSaving: false,
  previewMode: false,
  loadNotes: async () => {
    set({ isLoading: true, error: undefined });
    try {
      const notes = await fetchNotes();
      set({ notes });
      if (!get().activeId && notes.length > 0) {
        await get().selectNote(notes[0].id);
      }
    } catch (error) {
      set({ error: (error as Error).message });
    } finally {
      set({ isLoading: false });
    }
  },
  selectNote: async (id) => {
    set({ isLoading: true, error: undefined });
    try {
      const note = await fetchNote(id);
      set({ activeId: id, activeNote: note });
    } catch (error) {
      set({ error: (error as Error).message });
    } finally {
      set({ isLoading: false });
    }
  },
  createNew: async () => {
    set({ isSaving: true, error: undefined });
    try {
      const newItem = await createNote({ title: "Yeni Not", content: "" });
      const notes = await fetchNotes();
      set({ notes, activeId: newItem.id, activeNote: { id: newItem.id, title: newItem.title, content: "" } });
    } catch (error) {
      set({ error: (error as Error).message });
    } finally {
      set({ isSaving: false });
    }
  },
  updateActive: (title, content) => {
    const activeId = get().activeId;
    if (!activeId) {
      return;
    }
    set({ activeNote: { id: activeId, title, content } });
  },
  saveActive: async () => {
    const { activeId, activeNote } = get();
    if (!activeId || !activeNote) {
      return;
    }
    set({ isSaving: true, error: undefined });
    try {
      await updateNote(activeId, { title: activeNote.title, content: activeNote.content });
      const notes = await fetchNotes();
      set({ notes });
    } catch (error) {
      set({ error: (error as Error).message });
    } finally {
      set({ isSaving: false });
    }
  },
  removeActive: async () => {
    const { activeId } = get();
    if (!activeId) {
      return;
    }
    set({ isSaving: true, error: undefined });
    try {
      await deleteNote(activeId);
      const notes = await fetchNotes();
      set({ notes, activeId: undefined, activeNote: undefined });
      if (notes.length > 0) {
        await get().selectNote(notes[0].id);
      }
    } catch (error) {
      set({ error: (error as Error).message });
    } finally {
      set({ isSaving: false });
    }
  },
  removeById: async (id) => {
    const { activeId } = get();
    if (id === activeId) {
      await get().removeActive();
      return;
    }
    set({ isSaving: true, error: undefined });
    try {
      await deleteNote(id);
      const notes = await fetchNotes();
      set({ notes });
    } catch (error) {
      set({ error: (error as Error).message });
    } finally {
      set({ isSaving: false });
    }
  },
  retrySync: async () => {
    const { activeId } = get();
    if (!activeId) {
      return;
    }
    set({ isSaving: true, error: undefined });
    try {
      await syncNote(activeId);
      const notes = await fetchNotes();
      set({ notes });
    } catch (error) {
      set({ error: (error as Error).message });
    } finally {
      set({ isSaving: false });
    }
  },
  setSearch: (value) => set({ search: value }),
  togglePreview: () => set((state) => ({ previewMode: !state.previewMode }))
}));
