import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { ContactList } from '@/components/contacts/ContactList';
import { ContactForm } from '@/components/contacts/ContactForm';
import { validateVatIdFormat } from '@/lib/contacts';

// Mock the contacts API module
vi.mock('@/lib/contacts', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@/lib/contacts')>();
  return {
    ...actual,
    listContacts: vi.fn(),
    createContact: vi.fn(),
    updateContact: vi.fn(),
  };
});

import { listContacts, createContact } from '@/lib/contacts';

const mockContacts = {
  items: [
    {
      id: 'test-id-1',
      company_name: 'Müller Transport GmbH',
      address_city: 'Berlin',
      address_country: 'DE',
      role: 'kaeufer',
      vat_id: 'DE123456789',
      vat_id_status: 'ungeprueft',
      is_private: false,
      contact_persons: [],
    },
    {
      id: 'test-id-2',
      company_name: 'Van der Berg B.V.',
      address_city: 'Amsterdam',
      address_country: 'NL',
      role: 'verkaeufer',
      vat_id: 'NL123456789B01',
      vat_id_status: 'geprueft',
      is_private: false,
      contact_persons: [{ id: 'p1', contact_id: 'test-id-2', name: 'Jan' }],
    },
  ],
  total: 2,
  page: 1,
  page_size: 20,
};

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

  it('renders contact list with search and filter controls', async () => {
    vi.mocked(listContacts).mockResolvedValue(mockContacts);
    render(<ContactList />);

    await waitFor(() => {
      expect(screen.getByTestId('contact-list')).toBeInTheDocument();
    });

    expect(screen.getByTestId('filter-search')).toBeInTheDocument();
    expect(screen.getByTestId('filter-role')).toBeInTheDocument();
    expect(screen.getByTestId('filter-eu')).toBeInTheDocument();
    expect(screen.getByTestId('filter-sort')).toBeInTheDocument();
  });

  it('displays contacts in table after loading', async () => {
    vi.mocked(listContacts).mockResolvedValue(mockContacts);
    render(<ContactList />);

    await waitFor(() => {
      expect(screen.getByText('Müller Transport GmbH')).toBeInTheDocument();
    });

    expect(screen.getByText('Van der Berg B.V.')).toBeInTheDocument();
    expect(screen.getByText('Berlin')).toBeInTheDocument();
    expect(screen.getByText('Amsterdam')).toBeInTheDocument();
  });

  it('shows new contact button', async () => {
    vi.mocked(listContacts).mockResolvedValue(mockContacts);
    render(<ContactList />);

    await waitFor(() => {
      expect(screen.getByTestId('new-contact-btn')).toBeInTheDocument();
    });
  });

  it('shows error message on API failure', async () => {
    vi.mocked(listContacts).mockRejectedValue({
      error: { message: 'Network error' },
    });
    render(<ContactList />);

    await waitFor(() => {
      expect(screen.getByTestId('contact-error')).toBeInTheDocument();
    });

    expect(screen.getByText('Network error')).toBeInTheDocument();
  });

  it('shows loading state initially', async () => {
    vi.mocked(listContacts).mockImplementation(
      () => new Promise((resolve) => setTimeout(() => resolve(mockContacts), 100))
    );
    render(<ContactList />);

    expect(screen.getByTestId('contact-loading')).toBeInTheDocument();

    await waitFor(() => {
      expect(screen.getByText('Müller Transport GmbH')).toBeInTheDocument();
    });
  });
});

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

  it('renders form with all required fields', () => {
    render(<ContactForm mode="create" />);

    expect(screen.getByTestId('contact-form')).toBeInTheDocument();
    expect(screen.getByTestId('input-company_name')).toBeInTheDocument();
    expect(screen.getByTestId('input-role')).toBeInTheDocument();
    expect(screen.getByTestId('input-address_country')).toBeInTheDocument();
    expect(screen.getByTestId('input-vat_id')).toBeInTheDocument();
    expect(screen.getByTestId('input-phone')).toBeInTheDocument();
    expect(screen.getByTestId('input-email')).toBeInTheDocument();
    expect(screen.getByTestId('submit-button')).toBeInTheDocument();
  });

  it('shows EU/Inland toggle', () => {
    render(<ContactForm mode="create" />);

    expect(screen.getByTestId('eu-inland-toggle')).toBeInTheDocument();
    expect(screen.getByTestId('toggle-inland')).toBeInTheDocument();
    expect(screen.getByTestId('toggle-eu')).toBeInTheDocument();
  });

  it('defaults to Inland (DE) and shows DE placeholder for VAT ID', () => {
    render(<ContactForm mode="create" />);

    const inlandRadio = screen.getByTestId('toggle-inland') as HTMLInputElement;
    expect(inlandRadio.checked).toBe(true);
  });

  it('switches to EU mode and shows VAT ID hint when EU is selected', () => {
    render(<ContactForm mode="create" />);

    const euRadio = screen.getByTestId('toggle-eu');
    fireEvent.click(euRadio);

    expect(screen.getByTestId('vat-id-hint')).toBeInTheDocument();
  });

  it('validates VAT ID format and shows error for invalid DE VAT', () => {
    render(<ContactForm mode="create" />);

    const vatInput = screen.getByTestId('input-vat_id') as HTMLInputElement;
    fireEvent.change(vatInput, { target: { value: 'DE123' } });

    const submitBtn = screen.getByTestId('submit-button');
    fireEvent.click(submitBtn);

    expect(screen.getByText(/Invalid VAT ID format/)).toBeInTheDocument();
  });

  it('accepts valid DE VAT ID without error', async () => {
    vi.mocked(createContact).mockResolvedValue({
      id: 'new-id',
      company_name: 'Test GmbH',
      address_country: 'DE',
      role: 'kaeufer',
      vat_id_status: 'ungeprueft',
      is_private: false,
      contact_persons: [],
    });

    render(<ContactForm mode="create" />);

    const companyInput = screen.getByTestId('input-company_name');
    fireEvent.change(companyInput, { target: { value: 'Test GmbH' } });

    const vatInput = screen.getByTestId('input-vat_id');
    fireEvent.change(vatInput, { target: { value: 'DE123456789' } });

    const submitBtn = screen.getByTestId('submit-button');
    fireEvent.click(submitBtn);

    await waitFor(() => {
      expect(createContact).toHaveBeenCalled();
    });
  });

  it('requires company name', () => {
    render(<ContactForm mode="create" />);

    const submitBtn = screen.getByTestId('submit-button');
    fireEvent.click(submitBtn);

    expect(screen.getByText('Company name is required')).toBeInTheDocument();
  });
});

describe('validateVatIdFormat', () => {
  it('returns null for empty VAT ID', () => {
    expect(validateVatIdFormat('', 'DE')).toBeNull();
  });

  it('returns null for valid DE VAT ID', () => {
    expect(validateVatIdFormat('DE123456789', 'DE')).toBeNull();
  });

  it('returns error for invalid DE VAT ID (too short)', () => {
    const result = validateVatIdFormat('DE12345678', 'DE');
    expect(result).toContain('Invalid');
  });

  it('returns null for valid AT VAT ID', () => {
    expect(validateVatIdFormat('ATU12345678', 'AT')).toBeNull();
  });

  it('returns null for valid NL VAT ID', () => {
    expect(validateVatIdFormat('NL123456789B01', 'NL')).toBeNull();
  });

  it('returns error for non-EU country', () => {
    const result = validateVatIdFormat('US123456789', 'US');
    expect(result).toContain('not supported');
  });

  it('handles lowercase input', () => {
    expect(validateVatIdFormat('de123456789', 'DE')).toBeNull();
  });

  it('handles spaces in VAT ID', () => {
    expect(validateVatIdFormat('DE 123 456 789', 'DE')).toBeNull();
  });
});
