import { renderHook } from '@testing-library/react';
import { toast } from 'sonner';
import { describe, expect, it, vi, beforeEach } from 'vitest';

import { TOAST_MESSAGES, useToastMessages } from './useToastMessages';

vi.mock('sonner', () => ({
  toast: {
    success: vi.fn(),
    error: vi.fn(),
    warning: vi.fn(),
    info: vi.fn(),
  },
}));

describe('useToastMessages', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('successToast calls toast.success with message and duration', () => {
    const { result } = renderHook(() => useToastMessages());
    result.current.successToast('Saved!');
    expect(toast.success).toHaveBeenCalledWith('Saved!', { duration: 4000 });
  });

  it('errorToast calls toast.error with message and longer duration', () => {
    const { result } = renderHook(() => useToastMessages());
    result.current.errorToast('Something went wrong.');
    expect(toast.error).toHaveBeenCalledWith('Something went wrong.', { duration: 7000 });
  });

  it('warningToast calls toast.warning', () => {
    const { result } = renderHook(() => useToastMessages());
    result.current.warningToast('Unsaved changes.');
    expect(toast.warning).toHaveBeenCalledWith('Unsaved changes.', { duration: 5000 });
  });

  it('infoToast calls toast.info', () => {
    const { result } = renderHook(() => useToastMessages());
    result.current.infoToast('Processing...');
    expect(toast.info).toHaveBeenCalledWith('Processing...', { duration: 4000 });
  });

  it('exposes TOAST_MESSAGES constants', () => {
    const { result } = renderHook(() => useToastMessages());
    expect(result.current.TOAST_MESSAGES).toBe(TOAST_MESSAGES);
    expect(TOAST_MESSAGES.success.saved).toBe('Changes saved!');
    expect(TOAST_MESSAGES.error.generic).toBe('Something went wrong. Try again.');
  });

  it('error duration is longer than success duration', () => {
    // Error messages need more time to read
    const { result } = renderHook(() => useToastMessages());
    result.current.successToast('ok');
    result.current.errorToast('fail');
    const successCall = (toast.success as ReturnType<typeof vi.fn>).mock.calls[0][1];
    const errorCall = (toast.error as ReturnType<typeof vi.fn>).mock.calls[0][1];
    expect(errorCall.duration).toBeGreaterThan(successCall.duration);
  });
});
