import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import { pagesApi, type CustomPage, type CustomPageInput } from './pagesApi';

/**
 * Live store of user-created documentation pages.
 *
 * Custom pages are persisted in the @void-nav/api backend and surfaced both in
 * the sidebar (under a "Custom Pages" section) and as dynamic routes
 * (`/docs/custom/:slug`). This context keeps the sidebar, the dynamic page
 * renderer, and the editor in sync, and exposes mutations that optimistically
 * update the in-memory list.
 */

interface CustomPagesValue {
  pages: CustomPage[];
  loading: boolean;
  error: string | null;
  /** True while a refresh is in-flight (initial load or after a mutation). */
  refreshing: boolean;
  refresh: () => Promise<void>;
  create: (input: CustomPageInput) => Promise<CustomPage>;
  update: (id: string, input: Partial<CustomPageInput>) => Promise<CustomPage>;
  remove: (id: string) => Promise<void>;
  beautify: (id: string) => Promise<CustomPage>;
  getBySlug: (slug: string) => CustomPage | undefined;
}

const CustomPagesContext = createContext<CustomPagesValue | null>(null);

export function CustomPagesProvider({ children }: { children: ReactNode }) {
  const [pages, setPages] = useState<CustomPage[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const refresh = useCallback(async () => {
    setRefreshing(true);
    setError(null);
    try {
      const list = await pagesApi.list();
      setPages(list);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load custom pages');
    } finally {
      setRefreshing(false);
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  const create = useCallback(async (input: CustomPageInput) => {
    const page = await pagesApi.create(input);
    setPages((prev) => [...prev, page]);
    return page;
  }, []);

  const update = useCallback(async (id: string, input: Partial<CustomPageInput>) => {
    const page = await pagesApi.update(id, input);
    setPages((prev) => prev.map((p) => (p.id === id ? page : p)));
    return page;
  }, []);

  const remove = useCallback(async (id: string) => {
    await pagesApi.remove(id);
    setPages((prev) => prev.filter((p) => p.id !== id));
  }, []);

  const beautify = useCallback(async (id: string) => {
    const page = await pagesApi.beautify(id);
    setPages((prev) => prev.map((p) => (p.id === id ? page : p)));
    return page;
  }, []);

  const getBySlug = useCallback(
    (slug: string) => pages.find((p) => p.slug === slug),
    [pages],
  );

  const value = useMemo<CustomPagesValue>(
    () => ({ pages, loading, error, refreshing, refresh, create, update, remove, beautify, getBySlug }),
    [pages, loading, error, refreshing, refresh, create, update, remove, beautify, getBySlug],
  );

  return <CustomPagesContext.Provider value={value}>{children}</CustomPagesContext.Provider>;
}

export function useCustomPages(): CustomPagesValue {
  const ctx = useContext(CustomPagesContext);
  if (!ctx) throw new Error('useCustomPages must be used within a CustomPagesProvider');
  return ctx;
}
