/**
 * Tests for bulk spool creation and quick-add mode.
 *
 * Verifies:
 * - Quick-add toggle appears only in create mode
 * - Quick-add mode shows brand and subtype as optional (no asterisk)
 * - Quick-add mode hides slicer preset field
 * - Quick-add mode hides PA Profile tab
 * - Quantity field is only rendered in quick-add mode
 * - Quantity field is hidden in edit mode
 * - Bulk create calls bulkCreateSpools when quantity > 1
 * - Single quantity calls createSpool as before
 * - validateForm with quickAdd=true only requires material
 */

import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { screen, waitFor, fireEvent } from '@testing-library/react';
import { render } from '../utils';
import { SpoolFormModal } from '../../components/SpoolFormModal';
import { validateForm, defaultFormData } from '../../components/spool-form/types';
import type { InventorySpool } from '../../api/client';

// Mock the API client
vi.mock('../../api/client', () => ({
  api: {
    getSettings: vi.fn().mockResolvedValue({}),
    getAuthStatus: vi.fn().mockResolvedValue({ auth_enabled: false }),
    getCloudStatus: vi.fn().mockResolvedValue({ is_authenticated: false }),
    getFilamentPresets: vi.fn().mockResolvedValue([]),
    getSpoolCatalog: vi.fn().mockResolvedValue([]),
    getLocations: vi.fn().mockResolvedValue([]),
    getColorCatalog: vi.fn().mockResolvedValue([]),
    getLocalPresets: vi.fn().mockResolvedValue({ filament: [] }),
    getBuiltinFilaments: vi.fn().mockResolvedValue([]),
    getPrinters: vi.fn().mockResolvedValue([]),
    getSpoolUsageHistory: vi.fn().mockResolvedValue([]),
    createSpool: vi.fn().mockResolvedValue({ id: 99 }),
    bulkCreateSpools: vi.fn().mockResolvedValue([
      { id: 100, k_profiles: [] },
      { id: 101, k_profiles: [] },
      { id: 102, k_profiles: [] },
    ]),
    updateSpool: vi.fn().mockResolvedValue({ id: 1 }),
    saveSpoolKProfiles: vi.fn().mockResolvedValue([]),
  },
}));

// Mock the toast context
const mockShowToast = vi.fn();
vi.mock('../../contexts/ToastContext', async (importOriginal) => {
  const actual = await importOriginal<typeof import('../../contexts/ToastContext')>();
  return {
    ...actual,
    useToast: () => ({ showToast: mockShowToast }),
  };
});

const existingSpool: InventorySpool = {
  id: 1,
  material: 'PLA',
  subtype: 'Basic',
  brand: 'Polymaker',
  color_name: 'Red',
  rgba: 'FF0000FF',
  extra_colors: null,
  effect_type: null,
  label_weight: 1000,
  core_weight: 250,
  core_weight_catalog_id: null,
  weight_used: 300,
  slicer_filament: 'GFL99',
  slicer_filament_name: 'Generic PLA',
  nozzle_temp_min: null,
  nozzle_temp_max: null,
  note: null,
  added_full: null,
  last_used: null,
  encode_time: null,
  tag_uid: null,
  tray_uuid: null,
  data_origin: null,
  tag_type: null,
  archived_at: null,
  created_at: '2025-01-01T00:00:00Z',
  updated_at: '2025-01-01T00:00:00Z',
  k_profiles: [],
  cost_per_kg: null,
};

describe('validateForm with quickAdd', () => {
  it('requires only material in quick-add mode', () => {
    const result = validateForm({ ...defaultFormData, material: 'PLA' }, true);
    expect(result.isValid).toBe(true);
    expect(result.errors).toEqual({});
  });

  it('rejects empty material in quick-add mode', () => {
    const result = validateForm({ ...defaultFormData, material: '' }, true);
    expect(result.isValid).toBe(false);
    expect(result.errors.material).toBeDefined();
  });

  it('does not require slicer_filament in quick-add mode', () => {
    const result = validateForm(
      { ...defaultFormData, material: 'PETG', slicer_filament: '' },
      true,
    );
    expect(result.isValid).toBe(true);
  });

  it('does not require brand in quick-add mode', () => {
    const result = validateForm(
      { ...defaultFormData, material: 'ABS', brand: '' },
      true,
    );
    expect(result.isValid).toBe(true);
  });

  it('does not require subtype in quick-add mode', () => {
    const result = validateForm(
      { ...defaultFormData, material: 'TPU', subtype: '' },
      true,
    );
    expect(result.isValid).toBe(true);
  });

  it('requires all fields in full mode (quickAdd=false)', () => {
    const result = validateForm(defaultFormData, false);
    expect(result.isValid).toBe(false);
    expect(result.errors.material).toBeDefined();
    expect(result.errors.slicer_filament).toBeDefined();
    expect(result.errors.brand).toBeDefined();
    expect(result.errors.subtype).toBeDefined();
  });
});

describe('SpoolFormModal quick-add toggle', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('shows quick-add toggle in create mode', async () => {
    render(
      <SpoolFormModal
        isOpen={true}
        onClose={vi.fn()}
        mode="create"
        currencySymbol="$"
      />,
    );

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Add Spool' })).toBeInTheDocument();
    });

    expect(screen.getByText('Quick Add (Stock)')).toBeInTheDocument();
  });

  it('hides quick-add toggle in edit mode', async () => {
    render(
      <SpoolFormModal
        isOpen={true}
        onClose={vi.fn()}
        spool={existingSpool}
        mode="edit"
        currencySymbol="$"
      />,
    );

    await waitFor(() => {
      expect(screen.getByText('Edit Spool')).toBeInTheDocument();
    });

    expect(screen.queryByText('Quick Add (Stock)')).not.toBeInTheDocument();
  });

  it('hides PA Profile tab when quick-add is enabled', async () => {
    render(
      <SpoolFormModal
        isOpen={true}
        onClose={vi.fn()}
        mode="create"
        currencySymbol="$"
      />,
    );

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Add Spool' })).toBeInTheDocument();
    });

    // PA Profile tab should be visible initially
    expect(screen.getByText('PA Profile')).toBeInTheDocument();

    // Toggle quick-add on — the toggle is a button[role="switch"] sibling of the label
    const toggleButtons = screen.getAllByRole('button');
    const quickAddToggle = toggleButtons.find(btn =>
      btn.getAttribute('type') === 'button' &&
      btn.className.includes('rounded-full') &&
      btn.closest('div')?.textContent?.includes('Quick Add')
    );
    expect(quickAddToggle).toBeTruthy();
    fireEvent.click(quickAddToggle!);

    // PA Profile tab should be hidden
    await waitFor(() => {
      expect(screen.queryByText('PA Profile')).not.toBeInTheDocument();
    });
  });

  it('hides quantity field by default (non-quick-add)', async () => {
    render(
      <SpoolFormModal
        isOpen={true}
        onClose={vi.fn()}
        mode="create"
        currencySymbol="$"
      />,
    );

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Add Spool' })).toBeInTheDocument();
    });

    // Quantity field should NOT be visible in normal create mode
    expect(screen.queryByText('Quantity')).not.toBeInTheDocument();
  });

  it('shows quantity field only in quick-add mode', async () => {
    render(
      <SpoolFormModal
        isOpen={true}
        onClose={vi.fn()}
        mode="create"
        currencySymbol="$"
      />,
    );

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Add Spool' })).toBeInTheDocument();
    });

    // Toggle quick-add on
    const toggleButtons = screen.getAllByRole('button');
    const quickAddToggle = toggleButtons.find(btn =>
      btn.getAttribute('type') === 'button' &&
      btn.className.includes('rounded-full') &&
      btn.closest('div')?.textContent?.includes('Quick Add')
    );
    expect(quickAddToggle).toBeTruthy();
    fireEvent.click(quickAddToggle!);

    // Quantity field should now be visible
    await waitFor(() => {
      expect(screen.getByText('Quantity')).toBeInTheDocument();
    });
  });

  it('hides quantity field in edit mode', async () => {
    render(
      <SpoolFormModal
        isOpen={true}
        onClose={vi.fn()}
        spool={existingSpool}
        mode="edit"
        currencySymbol="$"
      />,
    );

    await waitFor(() => {
      expect(screen.getByText('Edit Spool')).toBeInTheDocument();
    });

    // Quantity field should NOT be visible in edit mode
    expect(screen.queryByText('Quantity')).not.toBeInTheDocument();
  });

  it('shows brand and subtype in quick-add mode without asterisk', async () => {
    render(
      <SpoolFormModal
        isOpen={true}
        onClose={vi.fn()}
        mode="create"
        currencySymbol="$"
      />,
    );

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Add Spool' })).toBeInTheDocument();
    });

    // Toggle quick-add on
    const toggleButtons = screen.getAllByRole('button');
    const quickAddToggle = toggleButtons.find(btn =>
      btn.getAttribute('type') === 'button' &&
      btn.className.includes('rounded-full') &&
      btn.closest('div')?.textContent?.includes('Quick Add')
    );
    fireEvent.click(quickAddToggle!);

    // Brand and Subtype should be visible (without asterisk = optional)
    await waitFor(() => {
      const brandLabel = screen.getByText('Brand');
      expect(brandLabel).toBeInTheDocument();
      expect(brandLabel.textContent).not.toContain('*');

      const subtypeLabel = screen.getByText('Subtype');
      expect(subtypeLabel).toBeInTheDocument();
      expect(subtypeLabel.textContent).not.toContain('*');
    });
  });
});
