/**
 * useWishlistMerge — after login, offer to merge anon localStorage wishlist
 * into the server wishlist via a dialog.
 *
 * Call `run()` after a successful auth flow. If anon wishlist has items,
 * the dialog opens. User can merge (POST to /api/wishlist/merge), discard
 * (clear local only), or dismiss (keep local, decide later).
 *
 * Also exposes `toasts` + `dismiss` for the host component to render
 * `<ToastViewport>`.
 */

'use client';

import { useState, useRef } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { getCsrfToken } from '@/lib/csrf';
import { useT } from '@/lib/i18n/react';
import { useToast } from '@/components/ui/overlays/Toast/useToast';
import { getAnonWishlistIds, clearAnonWishlist, countAnonWishlist } from './anonWishlistStore';

// ─── Types ────────────────────────────────────────────────────────────────────

interface MergeResponse {
  merged: number;
  skipped: number;
  total: number;
}

// ─── API call ─────────────────────────────────────────────────────────────────

async function postWishlistMerge(dealIds: string[]): Promise<MergeResponse> {
  const res = await fetch('/api/wishlist/merge', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-csrf-token': getCsrfToken(),
    },
    body: JSON.stringify({ dealIds }),
  });

  if (!res.ok) {
    throw new Error(`Merge failed: ${res.status}`);
  }

  return (await res.json()) as MergeResponse;
}

// ─── Return type ──────────────────────────────────────────────────────────────

export interface UseWishlistMergeReturn {
  /** Call after login. If anon wishlist has items, opens the merge dialog. No-op if empty. */
  run: () => Promise<void>;
  /** Props to spread onto <WishlistMergeDialog /> */
  dialogProps: {
    open: boolean;
    count: number;
    busy: boolean;
    onMerge: () => void;
    onDiscard: () => void;
    onDismiss: () => void;
  };
  /** Toast queue — render inside <ToastViewport toasts={toasts} dismiss={dismiss} /> */
  toasts: ReturnType<typeof useToast>['toasts'];
  /** Dismiss a specific toast by id */
  dismiss: ReturnType<typeof useToast>['dismiss'];
}

// ─── Hook ─────────────────────────────────────────────────────────────────────

export function useWishlistMerge(): UseWishlistMergeReturn {
  const queryClient = useQueryClient();
  const t = useT('wishlist');
  const { toast, toasts, dismiss } = useToast();

  const [open, setOpen] = useState(false);
  const [count, setCount] = useState(0);

  // Deferred resolver: run() returns a Promise that resolves only when the
  // dialog closes (merge success, discard, or dismiss). Auth-flow callers
  // await run() so they don't redirect until the user has acted.
  const resolverRef = useRef<(() => void) | null>(null);

  /** Resolve and clear the pending run() Promise. */
  const resolve = (): void => {
    resolverRef.current?.();
    resolverRef.current = null;
  };

  const mutation = useMutation({
    mutationFn: () => postWishlistMerge(getAnonWishlistIds()),

    onSuccess: (data) => {
      clearAnonWishlist();
      void queryClient.invalidateQueries({ queryKey: ['wishlist'] });
      toast({
        title: t('merge.toastSuccess').replace('{count}', String(data.merged)),
        tone: 'success',
      });
      resolve();
      setOpen(false);
    },

    onError: () => {
      // Leave local store intact — user can retry.
      // Do NOT resolve here: dialog stays open so user can retry or dismiss.
      toast({
        title: t('merge.toastError'),
        tone: 'danger',
      });
    },
  });

  /** Open dialog if anon wishlist is non-empty. Returns a Promise that
   *  resolves only when the dialog closes (merge success, discard, or dismiss).
   *  If the anon wishlist is empty, resolves immediately. */
  const run = (): Promise<void> => {
    const n = countAnonWishlist();
    if (n === 0) return Promise.resolve();
    return new Promise<void>((res) => {
      resolverRef.current = res;
      setCount(n);
      setOpen(true);
    });
  };

  /** Merge: fire API mutation. */
  const onMerge = (): void => {
    mutation.mutate();
  };

  /** Discard: clear local store + close without API call. */
  const onDiscard = (): void => {
    clearAnonWishlist();
    resolve();
    setOpen(false);
  };

  /** Dismiss: close only — local store is preserved. */
  const onDismiss = (): void => {
    resolve();
    setOpen(false);
  };

  return {
    run,
    dialogProps: {
      open,
      count,
      busy: mutation.isPending,
      onMerge,
      onDiscard,
      onDismiss,
    },
    toasts,
    dismiss,
  };
}
