// File: frontend/components/numbering/__tests__/cancel-number-form.test.tsx
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { CancelNumberForm } from '../cancel-number-form';
import { documentNumberingService } from '@/lib/services/document-numbering.service';
import { toast } from 'sonner';

vi.mock('@/lib/services/document-numbering.service', () => ({
  documentNumberingService: {
    cancelNumber: vi.fn(),
  },
}));

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

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

  it('renders correctly', () => {
    render(<CancelNumberForm />);
    expect(screen.getByRole('heading', { name: 'Cancel Number' })).toBeInTheDocument();
    expect(screen.getByLabelText('Document Number')).toBeInTheDocument();
    expect(screen.getByLabelText('Reason')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'Cancel Number' })).toBeInTheDocument();
  });

  it('shows validation error for empty fields', async () => {
    const user = userEvent.setup();
    render(<CancelNumberForm />);
    
    const button = screen.getByRole('button', { name: 'Cancel Number' });
    await user.click(button);
    
    await waitFor(() => {
      expect(screen.getByText('Document Number is required')).toBeInTheDocument();
      expect(screen.getByText('Reason must be at least 5 characters')).toBeInTheDocument();
    });
    
    expect(documentNumberingService.cancelNumber).not.toHaveBeenCalled();
  });

  it('shows validation error for short reason', async () => {
    const user = userEvent.setup();
    render(<CancelNumberForm />);
    
    await user.type(screen.getByLabelText('Document Number'), 'DOC-001');
    await user.type(screen.getByLabelText('Reason'), 'abc'); // too short
    
    const button = screen.getByRole('button', { name: 'Cancel Number' });
    await user.click(button);
    
    await waitFor(() => {
      expect(screen.getByText('Reason must be at least 5 characters')).toBeInTheDocument();
    });
    
    expect(documentNumberingService.cancelNumber).not.toHaveBeenCalled();
  });

  it('handles successful cancellation', async () => {
    const user = userEvent.setup();
    render(<CancelNumberForm />);
    
    await user.type(screen.getByLabelText('Document Number'), 'DOC-001');
    await user.type(screen.getByLabelText('Reason'), 'Generated by mistake');
    
    vi.mocked(documentNumberingService.cancelNumber).mockResolvedValue({} as any);
    
    const button = screen.getByRole('button', { name: 'Cancel Number' });
    await user.click(button);
    
    expect(documentNumberingService.cancelNumber).toHaveBeenCalledWith({
      documentNumber: 'DOC-001',
      reason: 'Generated by mistake',
    });
    
    await waitFor(() => {
      expect(toast.success).toHaveBeenCalledWith('Number cancelled successfully.');
    });
    
    // Check if form was reset
    expect(screen.getByLabelText('Document Number')).toHaveValue('');
    expect(screen.getByLabelText('Reason')).toHaveValue('');
  });

  it('handles cancellation failure', async () => {
    const user = userEvent.setup();
    render(<CancelNumberForm />);
    
    await user.type(screen.getByLabelText('Document Number'), 'DOC-001');
    await user.type(screen.getByLabelText('Reason'), 'Generated by mistake');
    
    vi.mocked(documentNumberingService.cancelNumber).mockRejectedValue(new Error('Failed'));
    
    const button = screen.getByRole('button', { name: 'Cancel Number' });
    await user.click(button);
    
    await waitFor(() => {
      expect(toast.error).toHaveBeenCalledWith('Failed to cancel number. It may not exist or is already cancelled.');
    });
    
    // Form is not reset on error
    expect(screen.getByLabelText('Document Number')).toHaveValue('DOC-001');
  });
});
