'use client';

import { useCallback, useEffect, useState } from 'react';
import type { DraftSummary, DraftFull } from '@/lib/db/draft-repo';

/**
 * Orchestriert den aktuell offenen Draft.
 *
 * Verantwortlichkeiten:
 *  - Liste aller Drafts halten (für Sidebar)
 *  - currentDraftId in localStorage persistieren
 *  - Beim Switch: Draft laden + Setter aufrufen, die den page.tsx-State rehydraten
 *  - Lazy Create: erster Save ohne offenen Draft erzeugt einen via createDraft()
 *
 * Die State-Setter (`onLoad`) gehören NICHT in den Hook — die App-Komponente
 * orchestriert das, weil sie weiß welche State-Slots zu hydraten sind.
 */

const LS_KEY = 'mailforge:currentDraftId';

export interface UseDraftOptions {
  /** Wird bei jedem Switch/Load gerufen — App-Komponente hydratet daraus den State. */
  onLoad: (draft: DraftFull) => void;
  /** Optional: nach Reset (kein aktiver Draft) — z.B. State leeren. */
  onClear?: () => void;
}

export interface UseDraftResult {
  drafts: DraftSummary[];
  currentDraftId: string | null;
  currentDraft: DraftSummary | null;
  loading: boolean;
  refreshDrafts: () => Promise<void>;
  /** Lädt Draft + ruft onLoad. State wird hydratet. */
  loadDraft: (id: string) => Promise<DraftFull | null>;
  /** Erzeugt neuen Draft, persistiert sofort, lädt + hydratet. */
  createDraft: (input: { workspaceId: string; name?: string }) => Promise<DraftFull | null>;
  /** Erzeugt neuen Draft mit Initial-State (briefing/tiptap), setzt currentDraftId
   *  OHNE onLoad zu rufen — der Aufrufer hält den State bereits lokal. Für Lazy-Create. */
  adoptDraft: (input: { workspaceId: string; name?: string; briefingJson: object; tiptapJson: object }) => Promise<string | null>;
  /** Wechselt zu "kein aktiver Draft". onClear wird aufgerufen. */
  clearDraft: () => void;
  /** Löscht in DB und entfernt aus Liste. */
  deleteDraft: (id: string) => Promise<boolean>;
  /** Dupliziert. */
  duplicateDraft: (id: string) => Promise<DraftFull | null>;
}

export function useDraft(opts: UseDraftOptions): UseDraftResult {
  const [drafts, setDrafts] = useState<DraftSummary[]>([]);
  const [currentDraftId, setCurrentDraftId] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  // Beim Mount: localStorage lesen (nur Client)
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const saved = window.localStorage.getItem(LS_KEY);
    if (saved) setCurrentDraftId(saved);
  }, []);

  // currentDraftId persist
  useEffect(() => {
    if (typeof window === 'undefined') return;
    if (currentDraftId) window.localStorage.setItem(LS_KEY, currentDraftId);
    else window.localStorage.removeItem(LS_KEY);
  }, [currentDraftId]);

  const refreshDrafts = useCallback(async () => {
    try {
      const res = await fetch('/api/drafts');
      const data = await res.json();
      setDrafts(data.drafts ?? []);
    } catch {
      setDrafts([]);
    }
  }, []);

  // Initial laden
  useEffect(() => {
    void refreshDrafts();
  }, [refreshDrafts]);

  const loadDraft = useCallback(async (id: string): Promise<DraftFull | null> => {
    setLoading(true);
    try {
      const res = await fetch(`/api/drafts/${id}`);
      if (!res.ok) return null;
      const data = await res.json();
      const draft = data.draft as DraftFull;
      setCurrentDraftId(id);
      opts.onLoad(draft);
      void refreshDrafts();
      return draft;
    } finally {
      setLoading(false);
    }
  }, [opts, refreshDrafts]);

  const createDraftFn = useCallback(async (input: { workspaceId: string; name?: string }): Promise<DraftFull | null> => {
    const res = await fetch('/api/drafts', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(input),
    });
    if (!res.ok) return null;
    const data = await res.json();
    const summary = data.draft as DraftSummary;
    return loadDraft(summary.id);
  }, [loadDraft]);

  const adoptDraft = useCallback(async (input: { workspaceId: string; name?: string; briefingJson: object; tiptapJson: object }): Promise<string | null> => {
    const res = await fetch('/api/drafts', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(input),
    });
    if (!res.ok) return null;
    const data = await res.json();
    const summary = data.draft as DraftSummary;
    setCurrentDraftId(summary.id);
    void refreshDrafts();
    // bewusst KEIN onLoad — der Aufrufer hat den State lokal und will ihn nicht überschreiben
    return summary.id;
  }, [refreshDrafts]);

  const clearDraft = useCallback(() => {
    setCurrentDraftId(null);
    opts.onClear?.();
  }, [opts]);

  const deleteDraftFn = useCallback(async (id: string): Promise<boolean> => {
    const res = await fetch(`/api/drafts/${id}`, { method: 'DELETE' });
    if (!res.ok) return false;
    if (currentDraftId === id) clearDraft();
    await refreshDrafts();
    return true;
  }, [currentDraftId, clearDraft, refreshDrafts]);

  const duplicateDraftFn = useCallback(async (id: string): Promise<DraftFull | null> => {
    const res = await fetch(`/api/drafts/${id}/duplicate`, { method: 'POST' });
    if (!res.ok) return null;
    const data = await res.json();
    return loadDraft(data.draft.id);
  }, [loadDraft]);

  // Initial-Load: wenn beim Mount eine ID in localStorage liegt, automatisch öffnen
  useEffect(() => {
    if (currentDraftId && drafts.length > 0) {
      const exists = drafts.find((d) => d.id === currentDraftId);
      if (exists) {
        // Nur laden wenn noch nicht geladen — heuristic: kein State-Setter, aber wir laden idempotent
        void loadDraft(currentDraftId);
      } else {
        // ID liegt im LS aber Draft existiert nicht mehr → Reset
        clearDraft();
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [drafts.length === 0]); // läuft genau einmal nach erstem Load der drafts-Liste

  const currentDraft = drafts.find((d) => d.id === currentDraftId) ?? null;

  return {
    drafts,
    currentDraftId,
    currentDraft,
    loading,
    refreshDrafts,
    loadDraft,
    createDraft: createDraftFn,
    adoptDraft,
    clearDraft,
    deleteDraft: deleteDraftFn,
    duplicateDraft: duplicateDraftFn,
  };
}
