import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import React from 'react';
import { LocationSelector, useShouldShowLocationSelector } from '../LocationSelector';
import { renderHook } from '@testing-library/react';

// Mock the useLocations hook
vi.mock('../../hooks/useLocations', () => ({
  useLocations: vi.fn(),
}));

import { useLocations } from '../../hooks/useLocations';

const createWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: { retry: false },
    },
  });
  return ({ children }: { children: React.ReactNode }) =>
    React.createElement(QueryClientProvider, { client: queryClient }, children);
};

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

  it('renders nothing when loading', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: undefined,
      isLoading: true,
      isError: false,
    } as any);

    const onChange = vi.fn();
    const { container } = render(
      <LocationSelector value={null} onChange={onChange} />,
      { wrapper: createWrapper() }
    );

    expect(container.firstChild).toBeNull();
  });

  it('renders nothing when there is only one location', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [{ id: 1, name: 'Main Office', is_active: true, is_primary: true }],
      isLoading: false,
      isError: false,
    } as any);

    const onChange = vi.fn();
    const { container } = render(
      <LocationSelector value={null} onChange={onChange} />,
      { wrapper: createWrapper() }
    );

    expect(container.firstChild).toBeNull();
  });

  it('renders selector when multiple locations exist', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [
        { id: 1, name: 'Main Office', is_active: true, is_primary: true },
        { id: 2, name: 'Branch Office', is_active: true, is_primary: false },
      ],
      isLoading: false,
      isError: false,
    } as any);

    const onChange = vi.fn();
    render(<LocationSelector value={null} onChange={onChange} />, {
      wrapper: createWrapper(),
    });

    expect(screen.getByLabelText('Location')).toBeInTheDocument();
    expect(screen.getByText('Main Office (Primary)')).toBeInTheDocument();
    expect(screen.getByText('Branch Office')).toBeInTheDocument();
  });

  it('shows single location when forceShow is true', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [{ id: 1, name: 'Main Office', is_active: true, is_primary: true }],
      isLoading: false,
      isError: false,
    } as any);

    const onChange = vi.fn();
    render(<LocationSelector value={null} onChange={onChange} forceShow />, {
      wrapper: createWrapper(),
    });

    expect(screen.getByLabelText('Location')).toBeInTheDocument();
  });

  it('calls onChange when selection changes', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [
        { id: 1, name: 'Main Office', is_active: true, is_primary: true },
        { id: 2, name: 'Branch Office', is_active: true, is_primary: false },
      ],
      isLoading: false,
      isError: false,
    } as any);

    const onChange = vi.fn();
    render(<LocationSelector value={null} onChange={onChange} />, {
      wrapper: createWrapper(),
    });

    const select = screen.getByLabelText('Location');
    fireEvent.change(select, { target: { value: '2' } });

    expect(onChange).toHaveBeenCalledWith(2);
  });

  it('marks inactive locations appropriately', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [
        { id: 1, name: 'Main Office', is_active: true, is_primary: true },
        { id: 2, name: 'Old Branch', is_active: false, is_primary: false },
      ],
      isLoading: false,
      isError: false,
    } as any);

    const onChange = vi.fn();
    render(<LocationSelector value={null} onChange={onChange} includeInactive />, {
      wrapper: createWrapper(),
    });

    expect(screen.getByText('Old Branch (Inactive)')).toBeInTheDocument();
  });

  it('displays custom label', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [
        { id: 1, name: 'Location A', is_active: true, is_primary: false },
        { id: 2, name: 'Location B', is_active: true, is_primary: false },
      ],
      isLoading: false,
      isError: false,
    } as any);

    const onChange = vi.fn();
    render(<LocationSelector value={null} onChange={onChange} label="Select Store" />, {
      wrapper: createWrapper(),
    });

    expect(screen.getByLabelText('Select Store')).toBeInTheDocument();
  });
});

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

  it('returns false when loading', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: undefined,
      isLoading: true,
    } as any);

    const { result } = renderHook(() => useShouldShowLocationSelector(), {
      wrapper: createWrapper(),
    });

    expect(result.current).toBe(false);
  });

  it('returns false when only one location', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [{ id: 1, name: 'Main', is_active: true }],
      isLoading: false,
    } as any);

    const { result } = renderHook(() => useShouldShowLocationSelector(), {
      wrapper: createWrapper(),
    });

    expect(result.current).toBe(false);
  });

  it('returns true when multiple locations exist', () => {
    vi.mocked(useLocations).mockReturnValue({
      data: [
        { id: 1, name: 'Main', is_active: true },
        { id: 2, name: 'Branch', is_active: true },
      ],
      isLoading: false,
    } as any);

    const { result } = renderHook(() => useShouldShowLocationSelector(), {
      wrapper: createWrapper(),
    });

    expect(result.current).toBe(true);
  });
});
