import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { AgentTypeList } from '@/components/agents/AgentTypeList';
import type { AgentTypeResponse } from '@/lib/api/types/agentTypes';

const mockAgentTypes: AgentTypeResponse[] = [
  {
    id: 'type-001',
    name: 'Product Owner',
    slug: 'product-owner',
    description: 'Manages product backlog and prioritizes features',
    expertise: ['requirements', 'user stories', 'prioritization'],
    personality_prompt: 'You are a Product Owner...',
    primary_model: 'claude-opus-4-5-20251101',
    fallback_models: ['claude-sonnet-4-20250514'],
    model_params: { temperature: 0.7, max_tokens: 8192, top_p: 0.95 },
    mcp_servers: ['gitea', 'knowledge'],
    tool_permissions: {},
    is_active: true,
    // Category and display fields
    category: 'development',
    icon: 'clipboard-check',
    color: '#3B82F6',
    sort_order: 10,
    typical_tasks: ['Manage backlog', 'Write user stories'],
    collaboration_hints: ['business-analyst', 'scrum-master'],
    created_at: '2025-01-15T00:00:00Z',
    updated_at: '2025-01-20T00:00:00Z',
    instance_count: 3,
  },
  {
    id: 'type-002',
    name: 'Software Architect',
    slug: 'software-architect',
    description: 'Designs system architecture and makes technology decisions',
    expertise: ['system design', 'api design', 'security'],
    personality_prompt: 'You are a Software Architect...',
    primary_model: 'claude-opus-4-5-20251101',
    fallback_models: [],
    model_params: { temperature: 0.5, max_tokens: 8192, top_p: 0.9 },
    mcp_servers: ['gitea'],
    tool_permissions: {},
    is_active: false,
    // Category and display fields
    category: 'development',
    icon: 'git-branch',
    color: '#3B82F6',
    sort_order: 40,
    typical_tasks: ['Design architecture', 'Create ADRs'],
    collaboration_hints: ['backend-engineer', 'devops-engineer'],
    created_at: '2025-01-10T00:00:00Z',
    updated_at: '2025-01-18T00:00:00Z',
    instance_count: 0,
  },
];

describe('AgentTypeList', () => {
  const defaultProps = {
    agentTypes: mockAgentTypes,
    isLoading: false,
    searchQuery: '',
    onSearchChange: jest.fn(),
    statusFilter: 'all',
    onStatusFilterChange: jest.fn(),
    categoryFilter: 'all',
    onCategoryFilterChange: jest.fn(),
    viewMode: 'grid' as const,
    onViewModeChange: jest.fn(),
    onSelect: jest.fn(),
    onCreate: jest.fn(),
  };

  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('renders page title and description', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(screen.getByText('Agent Types')).toBeInTheDocument();
    expect(
      screen.getByText('Configure templates for spawning AI agent instances')
    ).toBeInTheDocument();
  });

  it('renders create button', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(screen.getByRole('button', { name: /create agent type/i })).toBeInTheDocument();
  });

  it('renders search input', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(screen.getByPlaceholderText('Search agent types...')).toBeInTheDocument();
  });

  it('renders all agent types', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(screen.getByText('Product Owner')).toBeInTheDocument();
    expect(screen.getByText('Software Architect')).toBeInTheDocument();
  });

  it('shows description for each agent type', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(
      screen.getByText('Manages product backlog and prioritizes features')
    ).toBeInTheDocument();
    expect(
      screen.getByText('Designs system architecture and makes technology decisions')
    ).toBeInTheDocument();
  });

  it('shows active status badge for active agent types', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(screen.getByText('Active')).toBeInTheDocument();
    expect(screen.getByText('Inactive')).toBeInTheDocument();
  });

  it('shows expertise tags', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(screen.getByText('requirements')).toBeInTheDocument();
    expect(screen.getByText('user stories')).toBeInTheDocument();
  });

  it('shows instance count', () => {
    render(<AgentTypeList {...defaultProps} />);
    expect(screen.getByText('3 instances')).toBeInTheDocument();
    expect(screen.getByText('0 instances')).toBeInTheDocument();
  });

  it('calls onSelect when agent type card is clicked', async () => {
    const user = userEvent.setup();
    render(<AgentTypeList {...defaultProps} />);

    await user.click(screen.getByText('Product Owner'));
    expect(defaultProps.onSelect).toHaveBeenCalledWith('type-001');
  });

  it('calls onCreate when create button is clicked', async () => {
    const user = userEvent.setup();
    render(<AgentTypeList {...defaultProps} />);

    await user.click(screen.getByRole('button', { name: /create agent type/i }));
    expect(defaultProps.onCreate).toHaveBeenCalledTimes(1);
  });

  it('calls onSearchChange when search input changes', async () => {
    const user = userEvent.setup();
    render(<AgentTypeList {...defaultProps} />);

    const searchInput = screen.getByPlaceholderText('Search agent types...');
    await user.type(searchInput, 'architect');
    expect(defaultProps.onSearchChange).toHaveBeenCalled();
  });

  it('shows loading skeletons when isLoading is true', () => {
    const { container } = render(
      <AgentTypeList {...defaultProps} agentTypes={[]} isLoading={true} />
    );
    expect(container.querySelectorAll('.animate-pulse').length).toBeGreaterThan(0);
  });

  it('shows empty state when no agent types', () => {
    render(<AgentTypeList {...defaultProps} agentTypes={[]} />);
    expect(screen.getByText('No agent types found')).toBeInTheDocument();
    expect(screen.getByText('Create your first agent type to get started')).toBeInTheDocument();
  });

  it('shows filter hint in empty state when filters are applied', () => {
    render(<AgentTypeList {...defaultProps} agentTypes={[]} searchQuery="nonexistent" />);
    expect(screen.getByText('Try adjusting your search or filters')).toBeInTheDocument();
  });

  it('shows +N badge when expertise has more than 3 items', () => {
    const agentWithManySkills: AgentTypeResponse = {
      ...mockAgentTypes[0],
      expertise: ['skill1', 'skill2', 'skill3', 'skill4', 'skill5'],
    };
    render(<AgentTypeList {...defaultProps} agentTypes={[agentWithManySkills]} />);
    expect(screen.getByText('+2')).toBeInTheDocument();
  });

  it('supports keyboard navigation on agent type cards', async () => {
    const user = userEvent.setup();
    render(<AgentTypeList {...defaultProps} />);

    const cards = screen.getAllByRole('button', { name: /view .* agent type/i });
    cards[0].focus();
    await user.keyboard('{Enter}');
    expect(defaultProps.onSelect).toHaveBeenCalledWith('type-001');
  });

  it('supports Space key navigation on agent type cards', async () => {
    const user = userEvent.setup();
    const onSelect = jest.fn();
    render(<AgentTypeList {...defaultProps} onSelect={onSelect} />);

    const cards = screen.getAllByRole('button', { name: /view .* agent type/i });
    cards[0].focus();
    await user.keyboard(' ');
    expect(onSelect).toHaveBeenCalledWith('type-001');
  });

  it('shows fallback text when agent type has no description', () => {
    const agentWithoutDescription: AgentTypeResponse = {
      ...mockAgentTypes[0],
      description: '',
    };
    render(<AgentTypeList {...defaultProps} agentTypes={[agentWithoutDescription]} />);
    expect(screen.getByText('No description provided')).toBeInTheDocument();
  });

  it('applies custom className', () => {
    const { container } = render(<AgentTypeList {...defaultProps} className="custom-class" />);
    expect(container.firstChild).toHaveClass('custom-class');
  });

  describe('Category Filter', () => {
    it('renders category filter dropdown', () => {
      render(<AgentTypeList {...defaultProps} />);
      expect(screen.getByRole('combobox', { name: /filter by category/i })).toBeInTheDocument();
    });

    it('shows "All Categories" as default option', () => {
      render(<AgentTypeList {...defaultProps} categoryFilter="all" />);
      expect(screen.getByText('All Categories')).toBeInTheDocument();
    });

    it('displays category badge on agent cards', () => {
      render(<AgentTypeList {...defaultProps} />);
      // Both agents have 'development' category
      const developmentBadges = screen.getAllByText('Development');
      expect(developmentBadges.length).toBe(2);
    });

    it('shows filter hint in empty state when category filter is applied', () => {
      render(<AgentTypeList {...defaultProps} agentTypes={[]} categoryFilter="design" />);
      expect(screen.getByText('Try adjusting your search or filters')).toBeInTheDocument();
    });
  });

  describe('View Mode Toggle', () => {
    it('renders view mode toggle buttons', () => {
      render(<AgentTypeList {...defaultProps} />);
      expect(screen.getByRole('radio', { name: /grid view/i })).toBeInTheDocument();
      expect(screen.getByRole('radio', { name: /list view/i })).toBeInTheDocument();
    });

    it('renders grid view by default', () => {
      const { container } = render(<AgentTypeList {...defaultProps} viewMode="grid" />);
      // Grid view uses CSS grid
      expect(container.querySelector('.grid')).toBeInTheDocument();
    });

    it('renders list view when viewMode is list', () => {
      const { container } = render(<AgentTypeList {...defaultProps} viewMode="list" />);
      // List view uses space-y-3 for vertical stacking
      expect(container.querySelector('.space-y-3')).toBeInTheDocument();
    });

    it('calls onViewModeChange when grid toggle is clicked', async () => {
      const user = userEvent.setup();
      const onViewModeChange = jest.fn();
      render(
        <AgentTypeList {...defaultProps} viewMode="list" onViewModeChange={onViewModeChange} />
      );

      await user.click(screen.getByRole('radio', { name: /grid view/i }));
      expect(onViewModeChange).toHaveBeenCalledWith('grid');
    });

    it('calls onViewModeChange when list toggle is clicked', async () => {
      const user = userEvent.setup();
      const onViewModeChange = jest.fn();
      render(
        <AgentTypeList {...defaultProps} viewMode="grid" onViewModeChange={onViewModeChange} />
      );

      await user.click(screen.getByRole('radio', { name: /list view/i }));
      expect(onViewModeChange).toHaveBeenCalledWith('list');
    });

    it('shows list-specific loading skeletons when viewMode is list', () => {
      const { container } = render(
        <AgentTypeList {...defaultProps} agentTypes={[]} isLoading={true} viewMode="list" />
      );
      expect(container.querySelectorAll('.animate-pulse').length).toBeGreaterThan(0);
    });
  });

  describe('List View', () => {
    it('shows agent info in list rows', () => {
      render(<AgentTypeList {...defaultProps} viewMode="list" />);
      expect(screen.getByText('Product Owner')).toBeInTheDocument();
      expect(screen.getByText('Software Architect')).toBeInTheDocument();
    });

    it('shows category badge in list view', () => {
      render(<AgentTypeList {...defaultProps} viewMode="list" />);
      const developmentBadges = screen.getAllByText('Development');
      expect(developmentBadges.length).toBe(2);
    });

    it('shows expertise count in list view', () => {
      render(<AgentTypeList {...defaultProps} viewMode="list" />);
      // Both agents have 3 expertise areas
      const expertiseTexts = screen.getAllByText('3 expertise areas');
      expect(expertiseTexts.length).toBe(2);
    });

    it('calls onSelect when list row is clicked', async () => {
      const user = userEvent.setup();
      const onSelect = jest.fn();
      render(<AgentTypeList {...defaultProps} viewMode="list" onSelect={onSelect} />);

      await user.click(screen.getByText('Product Owner'));
      expect(onSelect).toHaveBeenCalledWith('type-001');
    });

    it('supports keyboard navigation on list rows', async () => {
      const user = userEvent.setup();
      const onSelect = jest.fn();
      render(<AgentTypeList {...defaultProps} viewMode="list" onSelect={onSelect} />);

      const rows = screen.getAllByRole('button', { name: /view .* agent type/i });
      rows[0].focus();
      await user.keyboard('{Enter}');
      expect(onSelect).toHaveBeenCalledWith('type-001');
    });
  });

  describe('Dynamic Icons', () => {
    it('renders agent icon in grid view', () => {
      const { container } = render(<AgentTypeList {...defaultProps} viewMode="grid" />);
      // Check for svg icons with lucide classes
      const icons = container.querySelectorAll('svg.lucide-clipboard-check, svg.lucide-git-branch');
      expect(icons.length).toBeGreaterThan(0);
    });

    it('renders agent icon in list view', () => {
      const { container } = render(<AgentTypeList {...defaultProps} viewMode="list" />);
      const icons = container.querySelectorAll('svg.lucide-clipboard-check, svg.lucide-git-branch');
      expect(icons.length).toBeGreaterThan(0);
    });
  });

  describe('Color Accent', () => {
    it('applies color to card border in grid view', () => {
      const { container } = render(<AgentTypeList {...defaultProps} viewMode="grid" />);
      const card = container.querySelector('[style*="border-top-color"]');
      expect(card).toBeInTheDocument();
    });

    it('applies color to row border in list view', () => {
      const { container } = render(<AgentTypeList {...defaultProps} viewMode="list" />);
      const row = container.querySelector('[style*="border-left-color"]');
      expect(row).toBeInTheDocument();
    });
  });

  describe('Category Badge Component', () => {
    it('does not render category badge when category is null', () => {
      const agentWithNoCategory: AgentTypeResponse = {
        ...mockAgentTypes[0],
        category: null,
      };
      render(<AgentTypeList {...defaultProps} agentTypes={[agentWithNoCategory]} />);
      expect(screen.queryByText('Development')).not.toBeInTheDocument();
    });
  });
});
