/**
 * DS-005: Component API Consistency Tests
 *
 * Verifies that the top UI components follow consistent prop naming conventions:
 * - `variant` prop uses consistent names across components
 * - `size` prop uses 'sm' | 'default' | 'lg' (no ad-hoc names)
 * - All components accept `className` and merge it with base classes
 * - All components forward refs
 */
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';

import { createRef } from 'react';

import { Badge } from './badge';
import { Button } from './button';
import { Input } from './input';

// ============================================
// Button — size + variant + className API
// ============================================

describe('Button — component API (DS-005)', () => {
  it('accepts size="sm"', () => {
    render(<Button size="sm">Small</Button>);
    const btn = screen.getByRole('button');
    expect(btn).toHaveClass('h-9');
  });

  it('accepts size="lg"', () => {
    render(<Button size="lg">Large</Button>);
    const btn = screen.getByRole('button');
    expect(btn).toHaveClass('h-11');
  });

  it('accepts variant="default"', () => {
    render(<Button variant="default">Default</Button>);
    expect(screen.getByRole('button')).toHaveClass('bg-primary');
  });

  it('accepts variant="destructive"', () => {
    render(<Button variant="destructive">Destructive</Button>);
    expect(screen.getByRole('button')).toHaveClass('bg-destructive');
  });

  it('accepts variant="outline"', () => {
    render(<Button variant="outline">Outline</Button>);
    expect(screen.getByRole('button')).toHaveClass('border');
  });

  it('accepts variant="secondary"', () => {
    render(<Button variant="secondary">Secondary</Button>);
    expect(screen.getByRole('button')).toHaveClass('bg-secondary');
  });

  it('accepts variant="ghost"', () => {
    render(<Button variant="ghost">Ghost</Button>);
    expect(screen.getByRole('button')).toHaveClass('hover:bg-accent');
  });

  it('accepts className and merges with base classes', () => {
    render(<Button className="my-custom-class">Test</Button>);
    const btn = screen.getByRole('button');
    expect(btn).toHaveClass('my-custom-class');
    expect(btn).toHaveClass('inline-flex'); // base class preserved
  });

  it('forwards ref', () => {
    const ref = createRef<HTMLButtonElement>();
    render(<Button ref={ref}>Test</Button>);
    expect(ref.current).toBeInstanceOf(HTMLButtonElement);
  });
});

// ============================================
// Badge — variant + className API
// ============================================

describe('Badge — component API (DS-005)', () => {
  it('accepts variant="default"', () => {
    const { container } = render(<Badge variant="default">Default</Badge>);
    expect(container.firstChild).toHaveClass('bg-primary');
  });

  it('accepts variant="secondary"', () => {
    const { container } = render(<Badge variant="secondary">Secondary</Badge>);
    expect(container.firstChild).toHaveClass('bg-secondary');
  });

  it('accepts variant="destructive"', () => {
    const { container } = render(<Badge variant="destructive">Destructive</Badge>);
    expect(container.firstChild).toHaveClass('bg-destructive');
  });

  it('accepts variant="outline"', () => {
    const { container } = render(<Badge variant="outline">Outline</Badge>);
    expect(container.firstChild).toHaveClass('text-foreground');
  });

  it('accepts variant="success"', () => {
    const { container } = render(<Badge variant="success">Success</Badge>);
    expect(container.firstChild).toHaveClass('bg-success');
  });

  it('accepts variant="warning"', () => {
    const { container } = render(<Badge variant="warning">Warning</Badge>);
    expect(container.firstChild).toHaveClass('bg-warning');
  });

  it('accepts className and merges with base classes', () => {
    const { container } = render(<Badge className="my-custom-class">Test</Badge>);
    expect(container.firstChild).toHaveClass('my-custom-class');
    expect(container.firstChild).toHaveClass('inline-flex'); // base class preserved
  });

  it('forwards ref', () => {
    const ref = createRef<HTMLDivElement>();
    render(<Badge ref={ref}>Test</Badge>);
    expect(ref.current).toBeInstanceOf(HTMLDivElement);
  });

  it('does not use size prop (Badge has no size variants — intentional)', () => {
    // Badge is intentionally size-less; this documents that decision
    // All badges are text-xs (small) by default — no need for size variants
    const { container } = render(<Badge>Label</Badge>);
    expect(container.firstChild).toHaveClass('text-xs');
  });
});

// ============================================
// Input — className API (Input has no size/variant — uses HTML type)
// ============================================

describe('Input — component API (DS-005)', () => {
  it('accepts className and merges with base classes', () => {
    render(<Input className="my-custom-class" data-testid="input" />);
    const input = screen.getByTestId('input');
    expect(input).toHaveClass('my-custom-class');
    expect(input).toHaveClass('flex'); // base class preserved
    expect(input).toHaveClass('h-10');
  });

  it('forwards ref', () => {
    const ref = createRef<HTMLInputElement>();
    render(<Input ref={ref} />);
    expect(ref.current).toBeInstanceOf(HTMLInputElement);
  });

  it('uses standard HTML type prop (not variant) — consistent with HTML input API', () => {
    render(<Input type="email" data-testid="input" />);
    expect(screen.getByTestId('input')).toHaveAttribute('type', 'email');
  });

  it('accepts all standard HTML input attributes', () => {
    render(
      <Input
        type="text"
        id="my-input"
        name="my-name"
        placeholder="Enter text"
        aria-label="Test input"
        data-testid="input"
      />,
    );
    const input = screen.getByTestId('input');
    expect(input).toHaveAttribute('id', 'my-input');
    expect(input).toHaveAttribute('name', 'my-name');
    expect(input).toHaveAttribute('placeholder', 'Enter text');
    expect(input).toHaveAttribute('aria-label', 'Test input');
  });
});

// ============================================
// Cross-component: shared naming conventions
// ============================================

describe('shared prop conventions across components (DS-005)', () => {
  it('Button and Badge both use "variant" prop name (not "color" or "type")', () => {
    // Renders without error using "variant" prop on both
    const { rerender } = render(<Button variant="default">Test</Button>);
    expect(screen.getByRole('button')).toHaveClass('bg-primary');

    rerender(<Badge variant="default">Test</Badge>);
    expect(screen.getByText('Test')).toHaveClass('bg-primary');
  });

  it('Button uses "size" prop with sm/default/lg/icon values', () => {
    const sizes = ['sm', 'default', 'lg', 'icon'] as const;
    sizes.forEach((size) => {
      const { unmount } = render(<Button size={size}>Test</Button>);
      expect(screen.getByRole('button')).toBeInTheDocument();
      unmount();
    });
  });
});
