import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

export interface Note {
  id: number;
  userId: number;
  title: string;
  content: string;
  color: string;
  isPinned: boolean;
  isArchived: boolean;
  createdAt: string;
  updatedAt: string;
  labelIds: number[];
}

export interface NoteLabel {
  id: number;
  userId: number;
  name: string;
  createdAt: string;
}

const BASE = `${import.meta.env.BASE_URL}api`.replace(/\/+/g, "/");

async function req<T>(path: string, init?: RequestInit): Promise<T> {
  const res = await fetch(`${BASE}${path}`, {
    credentials: "include",
    headers: { "Content-Type": "application/json", ...(init?.headers ?? {}) },
    ...init,
  });
  if (!res.ok) {
    let msg = `${res.status}`;
    try {
      const j = await res.json();
      msg = j.error ?? msg;
    } catch {}
    throw new Error(msg);
  }
  return res.json() as Promise<T>;
}

export const notesKey = (archived: boolean) => ["notes", { archived }] as const;
export const labelsKey = ["note-labels"] as const;

export function useNotes(archived: boolean) {
  return useQuery({
    queryKey: notesKey(archived),
    queryFn: () => req<Note[]>(`/notes?archived=${archived}`),
  });
}

export function useNoteLabels() {
  return useQuery({ queryKey: labelsKey, queryFn: () => req<NoteLabel[]>("/note-labels") });
}

export function useCreateNote() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (body: Partial<Note>) =>
      req<Note>("/notes", { method: "POST", body: JSON.stringify(body) }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["notes"] });
    },
  });
}

export function useUpdateNote() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, ...body }: Partial<Note> & { id: number }) =>
      req<Note>(`/notes/${id}`, { method: "PATCH", body: JSON.stringify(body) }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["notes"] });
    },
  });
}

export function useDeleteNote() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (id: number) => req<{ success: true }>(`/notes/${id}`, { method: "DELETE" }),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["notes"] }),
  });
}

export function useCreateLabel() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (name: string) =>
      req<NoteLabel>("/note-labels", { method: "POST", body: JSON.stringify({ name }) }),
    onSuccess: () => qc.invalidateQueries({ queryKey: labelsKey }),
  });
}

export function useUpdateLabel() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, name }: { id: number; name: string }) =>
      req<NoteLabel>(`/note-labels/${id}`, { method: "PATCH", body: JSON.stringify({ name }) }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: labelsKey });
      qc.invalidateQueries({ queryKey: ["notes"] });
    },
  });
}

export function useDeleteLabel() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (id: number) =>
      req<{ success: true }>(`/note-labels/${id}`, { method: "DELETE" }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: labelsKey });
      qc.invalidateQueries({ queryKey: ["notes"] });
    },
  });
}

export const NOTE_COLORS: { id: string; bg: string; ring: string }[] = [
  { id: "default", bg: "bg-white dark:bg-card", ring: "ring-slate-300" },
  { id: "red", bg: "bg-red-100 dark:bg-red-900/40", ring: "ring-red-400" },
  { id: "orange", bg: "bg-orange-100 dark:bg-orange-900/40", ring: "ring-orange-400" },
  { id: "yellow", bg: "bg-yellow-100 dark:bg-yellow-900/40", ring: "ring-yellow-400" },
  { id: "green", bg: "bg-green-100 dark:bg-green-900/40", ring: "ring-green-400" },
  { id: "teal", bg: "bg-teal-100 dark:bg-teal-900/40", ring: "ring-teal-400" },
  { id: "blue", bg: "bg-sky-100 dark:bg-sky-900/40", ring: "ring-sky-400" },
  { id: "purple", bg: "bg-purple-100 dark:bg-purple-900/40", ring: "ring-purple-400" },
  { id: "pink", bg: "bg-pink-100 dark:bg-pink-900/40", ring: "ring-pink-400" },
  { id: "gray", bg: "bg-slate-200 dark:bg-slate-800/60", ring: "ring-slate-400" },
];

export function colorBg(id: string): string {
  return NOTE_COLORS.find((c) => c.id === id)?.bg ?? NOTE_COLORS[0].bg;
}
