import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook, act, waitFor } from '@testing-library/react';
import { useItemCreate } from '@/hooks/useItemCreate';
import * as api from '@/lib/api';

// Mock api module
vi.mock('@/lib/api', () => ({
  inventoryApi: {
    createItem: vi.fn(),
    uploadItemPhoto: vi.fn(),
  },
}));

describe('useItemCreate Hook - Item Creation Flow Integration', () => {
  beforeEach(() => {
    vi.resetAllMocks();
  });

  it('should initialize with details step and empty form', () => {
    const { result } = renderHook(() => useItemCreate());

    expect(result.current.step).toBe('details');
    expect(result.current.formData.name).toBe('');
    expect(result.current.formData.category).toBe('');
    expect(result.current.formData.item_type).toBe('');
    expect(result.current.formData.quantity).toBe(1);
    expect(result.current.uploadedPhoto).toBeNull();
    expect(result.current.error).toBeNull();
  });

  it('should update form data', () => {
    const { result } = renderHook(() => useItemCreate());

    act(() => {
      result.current.setFormData({ name: 'Test Item' });
      result.current.setFormData({ category: 'Electronics' });
      result.current.setFormData({ item_type: 'Component' });
    });

    expect(result.current.formData.name).toBe('Test Item');
    expect(result.current.formData.category).toBe('Electronics');
    expect(result.current.formData.item_type).toBe('Component');
  });

  it('should navigate between steps', async () => {
    const { result } = renderHook(() => useItemCreate());

    expect(result.current.step).toBe('details');

    act(() => {
      result.current.goToStep('photo');
    });

    expect(result.current.step).toBe('photo');

    act(() => {
      result.current.nextStep();
    });

    expect(result.current.step).toBe('preview');

    act(() => {
      result.current.prevStep();
    });

    expect(result.current.step).toBe('photo');
  });

  it('should create item and return response', async () => {
    const mockCreateItem = vi.mocked(api.inventoryApi.createItem);
    mockCreateItem.mockResolvedValueOnce({ id: 123, name: 'Test Item' });

    const { result } = renderHook(() => useItemCreate());

    act(() => {
      result.current.setFormData({ name: 'Test Item' });
      result.current.setFormData({ category: 'Electronics' });
      result.current.setFormData({ item_type: 'Component' });
    });

    let createdItem;
    await act(async () => {
      createdItem = await result.current.submitItem(1);
    });

    expect(createdItem?.id).toBe(123);
    expect(mockCreateItem).toHaveBeenCalledWith(1, expect.objectContaining({
      name: 'Test Item',
      category: 'Electronics',
      item_type: 'Component',
    }));
  });

  it('should validate required fields on submission', async () => {
    const mockCreateItem = vi.mocked(api.inventoryApi.createItem);

    const { result } = renderHook(() => useItemCreate());

    // Try submitting without required fields (empty name)
    let submitResult;
    await act(async () => {
      submitResult = await result.current.submitItem(1);
    });

    // Should return undefined and set error
    expect(submitResult).toBeUndefined();
    expect(result.current.error).toBe('Item name is required');
    expect(mockCreateItem).not.toHaveBeenCalled();
  });

  it('should handle crop bounds independently', () => {
    const { result } = renderHook(() => useItemCreate());

    expect(result.current.cropBounds).toBeNull();

    act(() => {
      result.current.setCropBounds({ x: 10, y: 10, width: 100, height: 100 });
    });

    expect(result.current.cropBounds).toEqual({ x: 10, y: 10, width: 100, height: 100 });

    act(() => {
      result.current.setCropBounds(null);
    });

    expect(result.current.cropBounds).toBeNull();
  });

  it('should reset all state', async () => {
    const mockCreateItem = vi.mocked(api.inventoryApi.createItem);
    mockCreateItem.mockResolvedValueOnce({ id: 123 });

    const { result } = renderHook(() => useItemCreate());

    // Populate form and navigate
    await act(async () => {
      result.current.setFormData({ name: 'Test Item' });
      result.current.setFormData({ category: 'Electronics' });
      result.current.setFormData({ item_type: 'Component' });
      result.current.goToStep('photo');
      await result.current.submitItem(1);
    });

    // Verify populated state
    expect(result.current.formData.name).toBe('Test Item');
    expect(result.current.formData.category).toBe('Electronics');

    // Reset
    act(() => {
      result.current.reset();
    });

    expect(result.current.step).toBe('details');
    expect(result.current.formData.name).toBe('');
    expect(result.current.formData.category).toBe('');
    expect(result.current.uploadedPhoto).toBeNull();
    expect(result.current.error).toBeNull();
    expect(result.current.photoError).toBeNull();
  });

  it('should complete full workflow: details -> photo -> preview -> confirm', async () => {
    const mockCreateItem = vi.mocked(api.inventoryApi.createItem);
    const mockUploadPhoto = vi.mocked(api.inventoryApi.uploadItemPhoto);

    mockCreateItem.mockResolvedValueOnce({ id: 456 });
    mockUploadPhoto.mockResolvedValueOnce({
      status: 'ok',
      photo: {
        thumbnail_url: 'http://example.com/thumb.jpg',
        full_url: 'http://example.com/full.jpg',
        uploaded_at: '2024-01-01T00:00:00Z',
      },
    });

    const { result } = renderHook(() => useItemCreate());

    // Step 1: Details
    expect(result.current.step).toBe('details');

    act(() => {
      result.current.setFormData({
        name: 'Workflow Item',
        category: 'Electronics',
        item_type: 'Component',
        quantity: 5,
      });
    });

    await act(async () => {
      await result.current.submitItem(1);
    });

    // Step 2: Photo
    act(() => {
      result.current.goToStep('photo');
    });
    expect(result.current.step).toBe('photo');

    // Step 3: Preview
    act(() => {
      result.current.goToStep('preview');
      result.current.setCropBounds({ x: 0, y: 0, width: 100, height: 100 });
    });
    expect(result.current.step).toBe('preview');
    expect(result.current.cropBounds).not.toBeNull();

    // Step 4: Confirm
    act(() => {
      result.current.goToStep('confirm');
    });
    expect(result.current.step).toBe('confirm');

    // Reset (simulating completion)
    act(() => {
      result.current.reset();
    });

    expect(result.current.step).toBe('details');
    expect(result.current.formData.name).toBe('');
  });

  it('should call API with correct item data structure', async () => {
    const mockCreateItem = vi.mocked(api.inventoryApi.createItem);
    mockCreateItem.mockResolvedValueOnce({ id: 999 });

    const { result } = renderHook(() => useItemCreate());

    act(() => {
      result.current.setFormData({
        name: 'Precise Item',
        category: 'Tools',
        item_type: 'Power Tool',
        quantity: 10,
        barcode: 'BAR123',
        part_number: 'PT-001',
      });
    });

    await act(async () => {
      await result.current.submitItem(5);
    });

    expect(mockCreateItem).toHaveBeenCalledWith(5, expect.objectContaining({
      name: 'Precise Item',
      category: 'Tools',
      item_type: 'Power Tool',
      quantity: 10,
      barcode: 'BAR123',
      part_number: 'PT-001',
    }));
  });

  it('should handle API errors gracefully', async () => {
    const mockCreateItem = vi.mocked(api.inventoryApi.createItem);
    mockCreateItem.mockRejectedValueOnce(new Error('Network error'));

    const { result } = renderHook(() => useItemCreate());

    act(() => {
      result.current.setFormData({ name: 'Test Item' });
      result.current.setFormData({ category: 'Electronics' });
      result.current.setFormData({ item_type: 'Component' });
    });

    let submitResult;
    await act(async () => {
      submitResult = await result.current.submitItem(1);
    });

    // Should return undefined on error
    expect(submitResult).toBeUndefined();
    // Error should be set (may need to wait for state update)
    await waitFor(() => {
      expect(result.current.error).toBeTruthy();
    });
  });
});
