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

import { SpoonStatusBadge } from '../../src/components/spoons/spoon-status-badge';
import { ThreadStatusBadge } from '../../src/components/threads/thread-status-badge';
import { ConfirmButton } from '../../src/components/ui/confirm-button';
import { PillTabs } from '../../src/components/ui/pill-tabs';
import { SheetSelect } from '../../src/components/ui/sheet-select';
import { DiffPreview } from '../../src/components/workspace/diff-preview';

describe('mobile UI primitives', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  test('PillTabs renders labels and changes selection', () => {
    const onChange = vi.fn();

    render(
      <PillTabs
        tabs={[
          { label: 'Overview', value: 'overview' },
          { label: 'Settings', value: 'settings' },
        ]}
        value='overview'
        onChange={onChange}
      />,
    );

    fireEvent.click(screen.getByText('Settings'));

    expect(screen.getByText('Overview')).toBeTruthy();
    expect(onChange).toHaveBeenCalledWith('settings');
  });

  test('SheetSelect opens and chooses an option', () => {
    const onChange = vi.fn();

    render(
      <SheetSelect
        label='Provider'
        options={[
          { label: 'OpenAI', value: 'openai' },
          { label: 'Anthropic', value: 'anthropic' },
        ]}
        value='openai'
        onChange={onChange}
      />,
    );

    fireEvent.click(screen.getByText('OpenAI'));
    fireEvent.click(screen.getByText('Anthropic'));

    expect(onChange).toHaveBeenCalledWith('anthropic');
  });

  test('SheetSelect respects disabled state', () => {
    const onChange = vi.fn();

    render(
      <SheetSelect
        disabled
        label='Provider'
        options={[{ label: 'OpenAI', value: 'openai' }]}
        value='openai'
        onChange={onChange}
      />,
    );

    fireEvent.click(screen.getByText('OpenAI'));

    expect(onChange).not.toHaveBeenCalled();
  });

  test('ConfirmButton delegates confirmation to Alert', () => {
    const onConfirm = vi.fn();

    render(
      <ConfirmButton
        confirmLabel='Delete'
        message='Delete this?'
        title='Delete'
        onConfirm={onConfirm}
      >
        Remove
      </ConfirmButton>,
    );

    fireEvent.click(screen.getByText('Remove'));
    const calls = vi.mocked(Alert.alert).mock.calls;
    const confirm = calls[0]?.[2]?.[1];
    confirm?.onPress?.();

    expect(onConfirm).toHaveBeenCalledOnce();
  });

  test('DiffPreview truncates and expands long diffs', () => {
    const diff = Array.from({ length: 125 }, (_, index) =>
      index % 2 === 0 ? `+added ${index}` : `-removed ${index}`,
    ).join('\n');

    render(<DiffPreview content={diff} initialLines={3} />);

    expect(screen.getByText('+added 0')).toBeTruthy();
    expect(screen.queryByText('-removed 5')).toBeNull();

    fireEvent.click(screen.getByText('Show 122 more lines'));

    expect(screen.getByText('-removed 5')).toBeTruthy();
  });

  test('status badges render readable labels', () => {
    render(
      <>
        <SpoonStatusBadge status='up_to_date' />
        <ThreadStatusBadge status='waiting_for_user' />
      </>,
    );

    expect(screen.getByText('up to date')).toBeTruthy();
    expect(screen.getByText('waiting for user')).toBeTruthy();
  });
});
