import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { ToastProvider } from '@/components/ui/Toast';
import { I18nProvider } from '@/lib/i18n';
import { VehicleList } from '@/components/vehicles/VehicleList';
import { VehicleForm } from '@/components/vehicles/VehicleForm';
import { VehicleDetail } from '@/components/vehicles/VehicleDetail';
import { MobileDeStatus } from '@/components/vehicles/MobileDeStatus';

// Mock next/navigation
vi.mock('next/navigation', () => ({
  useRouter: () => ({
    push: vi.fn(),
    replace: vi.fn(),
    back: vi.fn(),
    refresh: vi.fn(),
  }),
  redirect: vi.fn(),
  usePathname: () => '/de/fahrzeuge',
  useSearchParams: () => new URLSearchParams(),
}));

// Mock the vehicles API module
vi.mock('@/lib/vehicles', () => ({
  listVehicles: vi.fn(),
  getVehicle: vi.fn(),
  createVehicle: vi.fn(),
  updateVehicle: vi.fn(),
  deleteVehicle: vi.fn(),
  pushToMobileDe: vi.fn(),
  getMobileDeStatus: vi.fn(),
}));

import {
  listVehicles as mockListVehicles,
  getVehicle as mockGetVehicle,
  createVehicle as mockCreateVehicle,
  deleteVehicle as mockDeleteVehicle,
  pushToMobileDe as mockPushToMobileDe,
  getMobileDeStatus as mockGetMobileDeStatus,
} from '@/lib/vehicles';

const mockVehicle = {
  id: 'vehicle-123',
  make: 'Mercedes-Benz',
  model: 'Actros',
  fin: 'WDB9066351L123456',
  year: 2020,
  first_registration: '2020-03-15',
  power_kw: 300,
  power_hp: 408,
  fuel_type: 'Diesel',
  transmission: 'Manual',
  color: 'White',
  condition: 'used',
  location: 'Berlin',
  availability: 'available',
  price: 45000.00,
  vehicle_type: 'lkw',
  lkw_type: 'sattelzugmaschine',
  machine_type: null,
  body_type: null,
  operating_hours: null,
  operating_hours_unit: null,
  mileage_km: 120000,
  description: 'Well maintained truck',
  created_at: '2025-01-01T12:00:00Z',
  updated_at: '2025-01-01T12:00:00Z',
  deleted_at: null,
};

function renderWithProviders(ui: React.ReactElement) {
  return render(
    <I18nProvider initialLocale="de">
      <ToastProvider>
        {ui}
      </ToastProvider>
    </I18nProvider>
  );
}

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

  it('renders the vehicle list with filters and table', async () => {
    (mockListVehicles as any).mockResolvedValue({
      items: [mockVehicle],
      total: 1,
      page: 1,
      page_size: 20,
    });

    renderWithProviders(<VehicleList />);

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

    expect(screen.getByTestId('vehicle-filters')).toBeInTheDocument();
    expect(screen.getByTestId('filter-search')).toBeInTheDocument();
    expect(screen.getByTestId('filter-type')).toBeInTheDocument();
    expect(screen.getByTestId('filter-availability')).toBeInTheDocument();
    expect(screen.getByTestId('filter-sort')).toBeInTheDocument();
  });

  it('displays vehicles in the table after loading', async () => {
    (mockListVehicles as any).mockResolvedValue({
      items: [mockVehicle],
      total: 1,
      page: 1,
      page_size: 20,
    });

    renderWithProviders(<VehicleList />);

    await waitFor(() => {
      expect(screen.getByText('Mercedes-Benz')).toBeInTheDocument();
      expect(screen.getByText('Actros')).toBeInTheDocument();
      expect(screen.getByText('WDB9066351L123456')).toBeInTheDocument();
    });
  });

  it('shows pagination when total > page_size', async () => {
    (mockListVehicles as any).mockResolvedValue({
      items: [mockVehicle],
      total: 40,
      page: 1,
      page_size: 20,
    });

    renderWithProviders(<VehicleList />);

    await waitFor(() => {
      expect(screen.getByTestId('vehicle-pagination')).toBeInTheDocument();
      expect(screen.getByText(/Page 1 of 2/)).toBeInTheDocument();
    });
  });

  it('shows error message on API failure', async () => {
    (mockListVehicles as any).mockRejectedValue({
      error: { code: 'UNKNOWN', message: 'Failed to load' },
    });

    renderWithProviders(<VehicleList />);

    await waitFor(() => {
      expect(screen.getByTestId('vehicle-error')).toBeInTheDocument();
      expect(screen.getByText('Failed to load')).toBeInTheDocument();
    });
  });

  it('calls listVehicles with type filter when changed', async () => {
    (mockListVehicles as any).mockResolvedValue({
      items: [],
      total: 0,
      page: 1,
      page_size: 20,
    });

    renderWithProviders(<VehicleList />);

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

    const typeSelect = screen.getByTestId('filter-type');
    fireEvent.change(typeSelect, { target: { value: 'lkw' } });

    await waitFor(() => {
    expect(mockListVehicles).toHaveBeenCalledWith(
      expect.objectContaining({ type: 'lkw', page: 1 })
    );
    });
  });
});

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

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

    expect(screen.getByTestId('vehicle-form')).toBeInTheDocument();
    expect(screen.getByTestId('input-make')).toBeInTheDocument();
    expect(screen.getByTestId('input-model')).toBeInTheDocument();
    expect(screen.getByTestId('input-fin')).toBeInTheDocument();
    expect(screen.getByTestId('input-price')).toBeInTheDocument();
    expect(screen.getByTestId('input-vehicle_type')).toBeInTheDocument();
    expect(screen.getByTestId('submit-button')).toBeInTheDocument();
  });

  it('shows validation errors for empty required fields', async () => {
    renderWithProviders(<VehicleForm mode="create" />);

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

    await waitFor(() => {
      expect(screen.getByText('Make is required')).toBeInTheDocument();
      expect(screen.getByText('Model is required')).toBeInTheDocument();
      expect(screen.getByText('FIN is required')).toBeInTheDocument();
    });
  });

  it('shows error for FIN not 17 characters', async () => {
    renderWithProviders(<VehicleForm mode="create" />);

    const finInput = screen.getByTestId('input-fin');
    fireEvent.change(finInput, { target: { value: 'SHORT' } });

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

    await waitFor(() => {
      expect(screen.getByText('FIN must be exactly 17 characters')).toBeInTheDocument();
    });
  });

  it('calls createVehicle on submit with valid data', async () => {
    (mockCreateVehicle as any).mockResolvedValue(mockVehicle);

    renderWithProviders(<VehicleForm mode="create" />);

    fireEvent.change(screen.getByTestId('input-make'), { target: { value: 'Volvo' } });
    fireEvent.change(screen.getByTestId('input-model'), { target: { value: 'FH16' } });
    fireEvent.change(screen.getByTestId('input-fin'), { target: { value: 'WDB9066351L123456' } });
    fireEvent.change(screen.getByTestId('input-price'), { target: { value: '85000' } });

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

    await waitFor(() => {
      expect(mockCreateVehicle).toHaveBeenCalledWith(
        expect.objectContaining({
          make: 'Volvo',
          model: 'FH16',
          fin: 'WDB9066351L123456',
          price: 85000,
        })
      );
    });
  });
});

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

  it('renders vehicle details after loading', async () => {
    (mockGetVehicle as any).mockResolvedValue(mockVehicle);
    (mockGetMobileDeStatus as any).mockResolvedValue({
      synced: false,
      sync_status: 'pending',
    });

    renderWithProviders(<VehicleDetail vehicleId="vehicle-123" />);

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

    expect(screen.getByTestId('vehicle-detail-title')).toHaveTextContent('Mercedes-Benz Actros');
    const fieldsContainer = screen.getByTestId('vehicle-detail-fields');
    expect(fieldsContainer).toHaveTextContent('WDB9066351L123456');
    expect(fieldsContainer).toHaveTextContent('lkw');
    expect(fieldsContainer).toHaveTextContent('available');
  });

  it('shows mobile.de status section', async () => {
    (mockGetVehicle as any).mockResolvedValue(mockVehicle);
    (mockGetMobileDeStatus as any).mockResolvedValue({
      synced: true,
      ad_id: 'ad-123',
      synced_at: '2025-01-01T12:00:00Z',
      sync_status: 'synced',
    });

    renderWithProviders(<VehicleDetail vehicleId="vehicle-123" />);

    await waitFor(() => {
      expect(screen.getByTestId('mobile-de-status')).toBeInTheDocument();
    });

    expect(screen.getByTestId('mobile-de-sync-status')).toHaveTextContent('Synced');
  });

  it('shows error message on API failure', async () => {
    (mockGetVehicle as any).mockRejectedValue({
      error: { code: 'VEHICLE_NOT_FOUND', message: 'Vehicle not found' },
    });

    renderWithProviders(<VehicleDetail vehicleId="nonexistent" />);

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

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

  it('renders with pending status when no listing exists', async () => {
    (mockGetMobileDeStatus as any).mockResolvedValue({
      synced: false,
      sync_status: 'pending',
    });

    renderWithProviders(<MobileDeStatus vehicleId="vehicle-123" />);

    await waitFor(() => {
      expect(screen.getByTestId('mobile-de-sync-status')).toHaveTextContent('Pending');
    });

    expect(screen.getByTestId('mobile-de-synced')).toHaveTextContent('No');
  });

  it('shows synced status after successful push', async () => {
    (mockGetMobileDeStatus as any).mockResolvedValue({
      synced: true,
      ad_id: 'ad-456',
      synced_at: '2025-06-01T10:00:00Z',
      sync_status: 'synced',
    });

    renderWithProviders(<MobileDeStatus vehicleId="vehicle-123" />);

    await waitFor(() => {
      expect(screen.getByTestId('mobile-de-sync-status')).toHaveTextContent('Synced');
    });

    expect(screen.getByTestId('mobile-de-synced')).toHaveTextContent('Yes');
    expect(screen.getByText('ad-456')).toBeInTheDocument();
  });

  it('shows error log when sync failed', async () => {
    (mockGetMobileDeStatus as any).mockResolvedValue({
      synced: false,
      sync_status: 'fehler',
      error_log: 'HTTP 500: Internal Server Error',
    });

    renderWithProviders(<MobileDeStatus vehicleId="vehicle-123" />);

    await waitFor(() => {
      expect(screen.getByTestId('mobile-de-sync-status')).toHaveTextContent('Error');
      expect(screen.getByTestId('mobile-de-error-log')).toBeInTheDocument();
      expect(screen.getByText(/HTTP 500/)).toBeInTheDocument();
    });
  });

  it('calls pushToMobileDe when push button is clicked', async () => {
    (mockGetMobileDeStatus as any).mockResolvedValue({
      synced: false,
      sync_status: 'pending',
    });
    (mockPushToMobileDe as any).mockResolvedValue({
      message: 'Push queued',
      vehicle_id: 'vehicle-123',
    });

    renderWithProviders(<MobileDeStatus vehicleId="vehicle-123" />);

    await waitFor(() => {
      expect(screen.getByTestId('mobile-de-push-button')).toBeInTheDocument();
    });

    fireEvent.click(screen.getByTestId('mobile-de-push-button'));

    await waitFor(() => {
      expect(mockPushToMobileDe).toHaveBeenCalledWith('vehicle-123');
    });
  });
});
