import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';

const { mockImportProducts } = vi.hoisted(() => ({
  mockImportProducts: vi.fn(),
}));

vi.mock('@/services/products', () => ({
  importProducts: mockImportProducts,
}));

import { ImportDialog } from '../../../../src/app/(dashboard)/products/ImportDialog';

beforeEach(() => vi.clearAllMocks());

const defaultProps = {
  open: true,
  onClose: vi.fn(),
  householdId: 'hh1',
  onSuccess: vi.fn(),
};

describe('ImportDialog', () => {
  it('renders nothing when closed', () => {
    const { container } = render(<ImportDialog {...defaultProps} open={false} />);
    expect(container.innerHTML).toBe('');
  });

  it('renders Import Products title when open', () => {
    render(<ImportDialog {...defaultProps} />);
    expect(screen.getByText('Import Products')).toBeInTheDocument();
  });

  it('shows file chooser button', () => {
    render(<ImportDialog {...defaultProps} />);
    expect(screen.getByText('Choose .csv or .json file...')).toBeInTheDocument();
  });

  it('Upload button is disabled without file', () => {
    render(<ImportDialog {...defaultProps} />);
    expect(screen.getByText('Upload')).toBeDisabled();
  });

  it('shows file name after selection', () => {
    render(<ImportDialog {...defaultProps} />);

    const input = document.querySelector('input[type="file"]') as HTMLInputElement;
    const file = new File(['name,category\nTest,other'], 'products.csv', {
      type: 'text/csv',
    });
    fireEvent.change(input, { target: { files: [file] } });

    expect(screen.getByText('products.csv')).toBeInTheDocument();
  });

  it('uploads file and shows success result', async () => {
    mockImportProducts.mockResolvedValue({
      imported: 5,
      skippedDuplicates: 1,
      errors: [],
    });

    render(<ImportDialog {...defaultProps} />);

    const input = document.querySelector('input[type="file"]') as HTMLInputElement;
    const file = new File(['data'], 'products.csv', { type: 'text/csv' });
    fireEvent.change(input, { target: { files: [file] } });
    fireEvent.click(screen.getByText('Upload'));

    await waitFor(() => {
      expect(screen.getByText('Import complete')).toBeInTheDocument();
    });
    expect(screen.getByText('5')).toBeInTheDocument();
    expect(screen.getByText('1')).toBeInTheDocument();
    expect(defaultProps.onSuccess).toHaveBeenCalled();
  });

  it('shows errors in result', async () => {
    mockImportProducts.mockResolvedValue({
      imported: 0,
      skippedDuplicates: 0,
      errors: [{ row: 2, message: 'Missing name' }],
    });

    render(<ImportDialog {...defaultProps} />);

    const input = document.querySelector('input[type="file"]') as HTMLInputElement;
    const file = new File(['data'], 'products.csv', { type: 'text/csv' });
    fireEvent.change(input, { target: { files: [file] } });
    fireEvent.click(screen.getByText('Upload'));

    await waitFor(() => {
      expect(screen.getByText('Import complete')).toBeInTheDocument();
    });
    expect(screen.getByText(/Row 2: Missing name/)).toBeInTheDocument();
    expect(defaultProps.onSuccess).not.toHaveBeenCalled();
  });

  it('shows error on import failure', async () => {
    mockImportProducts.mockRejectedValue(new Error('Network error'));

    render(<ImportDialog {...defaultProps} />);

    const input = document.querySelector('input[type="file"]') as HTMLInputElement;
    const file = new File(['data'], 'products.csv', { type: 'text/csv' });
    fireEvent.change(input, { target: { files: [file] } });
    fireEvent.click(screen.getByText('Upload'));

    await waitFor(() => {
      expect(screen.getByText('Network error')).toBeInTheDocument();
    });
  });

  it('shows fallback error on non-Error rejection', async () => {
    mockImportProducts.mockRejectedValue('unknown');

    render(<ImportDialog {...defaultProps} />);

    const input = document.querySelector('input[type="file"]') as HTMLInputElement;
    const file = new File(['data'], 'products.csv', { type: 'text/csv' });
    fireEvent.change(input, { target: { files: [file] } });
    fireEvent.click(screen.getByText('Upload'));

    await waitFor(() => {
      expect(screen.getByText('Import failed')).toBeInTheDocument();
    });
  });

  it('closes dialog via Cancel button', () => {
    render(<ImportDialog {...defaultProps} />);
    fireEvent.click(screen.getByText('Cancel'));
    expect(defaultProps.onClose).toHaveBeenCalled();
  });

  it('closes dialog via Close button after result', async () => {
    mockImportProducts.mockResolvedValue({
      imported: 1,
      skippedDuplicates: 0,
      errors: [],
    });

    render(<ImportDialog {...defaultProps} />);

    const input = document.querySelector('input[type="file"]') as HTMLInputElement;
    const file = new File(['data'], 'products.csv', { type: 'text/csv' });
    fireEvent.change(input, { target: { files: [file] } });
    fireEvent.click(screen.getByText('Upload'));

    await waitFor(() => {
      expect(screen.getByText('Import complete')).toBeInTheDocument();
    });

    fireEvent.click(screen.getByText('Close'));
    expect(defaultProps.onClose).toHaveBeenCalled();
  });
});
