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

import { LoadingButton } from './loading-button';

describe('LoadingButton', () => {
  it('renders children when not loading', () => {
    render(<LoadingButton loading={false}>Save</LoadingButton>);

    expect(screen.getByRole('button', { name: 'Save' })).toBeInTheDocument();
  });

  it('shows loading text when loading', () => {
    render(
      <LoadingButton loading={true} loadingText="Saving...">
        Save
      </LoadingButton>,
    );

    expect(screen.getByRole('button', { name: /save in progress/i })).toBeInTheDocument();
  });

  it('shows default loading text when loading and no loadingText provided', () => {
    render(<LoadingButton loading={true}>Save</LoadingButton>);

    expect(screen.getByRole('button', { name: /save in progress/i })).toBeInTheDocument();
  });

  it('sets aria-busy="true" when loading', () => {
    render(<LoadingButton loading={true}>Save</LoadingButton>);

    expect(screen.getByRole('button')).toHaveAttribute('aria-busy', 'true');
  });

  it('does not set aria-busy when not loading', () => {
    render(<LoadingButton loading={false}>Save</LoadingButton>);

    expect(screen.getByRole('button')).not.toHaveAttribute('aria-busy');
  });

  it('renders spinner with aria-hidden="true" when loading', () => {
    const { container } = render(<LoadingButton loading={true}>Save</LoadingButton>);

    const spinner = container.querySelector('[aria-hidden="true"]');
    expect(spinner).not.toBeNull();
  });

  it('does not render spinner when not loading', () => {
    const { container } = render(<LoadingButton loading={false}>Save</LoadingButton>);

    const spinner = container.querySelector('[aria-hidden="true"]');
    expect(spinner).toBeNull();
  });

  it('disables the button when loading', () => {
    render(<LoadingButton loading={true}>Save</LoadingButton>);

    expect(screen.getByRole('button')).toBeDisabled();
  });

  it('disables the button when disabled prop is true', () => {
    render(
      <LoadingButton loading={false} disabled={true}>
        Save
      </LoadingButton>,
    );

    expect(screen.getByRole('button')).toBeDisabled();
  });

  // ============================================
  // Accessible loading state announcement tests (UX-004)
  // ============================================

  describe('accessible loading state announcement via aria-label', () => {
    it('updates aria-label to include "in progress" when loading with string children', () => {
      render(<LoadingButton loading={true}>Save</LoadingButton>);

      const button = screen.getByRole('button');
      expect(button).toHaveAttribute('aria-label', 'Save in progress');
    });

    it('uses "Processing in progress" when children is not a string', () => {
      render(
        <LoadingButton loading={true}>
          <span>Custom Content</span>
        </LoadingButton>,
      );

      const button = screen.getByRole('button');
      expect(button).toHaveAttribute('aria-label', 'Processing in progress');
    });

    it('does not set aria-label when not loading', () => {
      render(<LoadingButton loading={false}>Save</LoadingButton>);

      const button = screen.getByRole('button');
      expect(button).not.toHaveAttribute('aria-label');
    });

    it('updates aria-label when loading state changes from false to true', () => {
      const { rerender } = render(<LoadingButton loading={false}>Save</LoadingButton>);

      const button = screen.getByRole('button');
      expect(button).not.toHaveAttribute('aria-label');

      rerender(<LoadingButton loading={true}>Save</LoadingButton>);

      expect(button).toHaveAttribute('aria-label', 'Save in progress');
    });

    it('removes aria-label when loading state changes from true to false', () => {
      const { rerender } = render(<LoadingButton loading={true}>Save</LoadingButton>);

      const button = screen.getByRole('button');
      expect(button).toHaveAttribute('aria-label', 'Save in progress');

      rerender(<LoadingButton loading={false}>Save</LoadingButton>);

      expect(button).not.toHaveAttribute('aria-label');
    });

    it('includes custom loading text in aria-label when provided', () => {
      render(
        <LoadingButton loading={true} loadingText="Saving...">
          Save
        </LoadingButton>,
      );

      const button = screen.getByRole('button');
      // aria-label is based on original children, not loadingText
      expect(button).toHaveAttribute('aria-label', 'Save in progress');
    });
  });
});
