import { MutableRefObject, useCallback, useState } from 'react';

type ApiClient = {
  get: (path: string) => Promise<{ data: unknown }>;
  post: (path: string, body: unknown) => Promise<{ data: unknown }>;
  patch: (path: string, body: unknown) => Promise<{ data: unknown }>;
  delete: (path: string) => Promise<{ data: unknown }>;
};

interface CorrespondentEntry {
  id?: string;
  name?: string;
  [key: string]: unknown;
}

interface UseCorrespondentsOptions {
  apiClient: ApiClient;
  notifyApiError: (error: unknown, fallback: string) => void;
  setStatusMessage: (message: string, variant?: string) => void;
  tenantIdRef: MutableRefObject<string | null>;
  mapDocumentCaches?: (mapper: (doc: any) => any) => void;
}

const useCorrespondents = ({
  apiClient,
  notifyApiError,
  setStatusMessage,
  tenantIdRef,
  mapDocumentCaches,
}: UseCorrespondentsOptions) => {
  const [correspondents, setCorrespondents] = useState<CorrespondentEntry[]>([]);

  const refreshCorrespondents = useCallback(async () => {
    const requestTenantId = tenantIdRef.current;
    try {
      const { data } = await apiClient.get('/correspondents');
      if (tenantIdRef.current !== requestTenantId) {
        return;
      }
      setCorrespondents(data || []);
    } catch (error) {
      if (tenantIdRef.current !== requestTenantId) {
        return;
      }
      notifyApiError(error, 'Unable to load correspondents.');
    }
  }, [apiClient, notifyApiError, tenantIdRef]);

  const handleCorrespondentUpdate = useCallback(
    async (correspondentId: string, changes: { name?: string }) => {
      if (correspondentId == null) {
        throw new Error('Missing correspondent identifier.');
      }

      const payload: Record<string, unknown> = {};
      if (changes?.name != null) {
        const trimmed = changes.name.trim();
        if (!trimmed) {
          throw new Error('Correspondent name cannot be empty.');
        }
        payload.name = trimmed;
      }

      if (Object.keys(payload).length === 0) {
        return false;
      }

      try {
        await apiClient.patch(`/correspondents/${correspondentId}`, payload);
        await refreshCorrespondents();
        setStatusMessage('Correspondent updated.', 'success');
        return true;
      } catch (error) {
        const message = error.response?.data?.error || 'Failed to update correspondent.';
        notifyApiError(error, message);
        throw new Error(message);
      }
    },
    [apiClient, notifyApiError, refreshCorrespondents, setStatusMessage],
  );

  const handleCorrespondentCreate = useCallback(
    async ({ name }: { name?: string }) => {
      const trimmed = name?.trim?.() || '';
      if (!trimmed) {
        throw new Error('Correspondent name is required.');
      }
      try {
        const { data } = await apiClient.post('/correspondents', { name: trimmed });
        await refreshCorrespondents();
        setStatusMessage('Correspondent created.', 'success');
        return data;
      } catch (error) {
        const message = error.response?.data?.error || 'Failed to create correspondent.';
        notifyApiError(error, message);
        throw new Error(message);
      }
    },
    [apiClient, notifyApiError, refreshCorrespondents, setStatusMessage],
  );

  const handleCorrespondentDelete = useCallback(
    async (correspondentId: string) => {
      if (correspondentId == null) {
        throw new Error('Missing correspondent identifier.');
      }

      const stripFromDoc = (doc: any) => {
        if (!doc || !Array.isArray(doc.correspondents)) {
          return doc;
        }
        const next = doc.correspondents.filter((entry) => entry.id !== correspondentId);
        if (next.length === doc.correspondents.length) {
          return doc;
        }
        return { ...doc, correspondents: next };
      };

      try {
        await apiClient.delete(`/correspondents/${correspondentId}`);
        await refreshCorrespondents();

        mapDocumentCaches?.(stripFromDoc);

        setStatusMessage('Correspondent deleted.', 'success');
        return true;
      } catch (error) {
        const message = error.response?.data?.error || 'Failed to delete correspondent.';
        notifyApiError(error, message);
        throw new Error(message);
      }
    },
    [apiClient, mapDocumentCaches, notifyApiError, refreshCorrespondents, setStatusMessage],
  );

  return {
    correspondents,
    refreshCorrespondents,
    handleCorrespondentCreate,
    handleCorrespondentUpdate,
    handleCorrespondentDelete,
    setCorrespondents,
  };
};

export default useCorrespondents;
