import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { ServiceAccountsSection } from '../ServiceAccountsSection';

describe('ServiceAccountsSection', () => {
  const mockOnCreate = vi.fn();
  const mockOnDelete = vi.fn();

  const mockAccounts = [
    {
      id: 1,
      name: 'my-pipeline',
      client_id: 'abc-123-xyz',
      created_at: '2024-12-01T00:00:00Z',
    },
    {
      id: 2,
      name: 'etl-job',
      client_id: 'def-456-uvw',
      created_at: '2024-12-02T00:00:00Z',
    },
  ];

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

  it('renders empty state when no accounts', () => {
    render(
      <ServiceAccountsSection
        accounts={[]}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    expect(screen.getByText(/No service accounts yet/i)).toBeInTheDocument();
  });

  it('renders accounts list', () => {
    render(
      <ServiceAccountsSection
        accounts={mockAccounts}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    expect(screen.getByText('my-pipeline')).toBeInTheDocument();
    expect(screen.getByText('etl-job')).toBeInTheDocument();
    expect(screen.getByText('abc-123-xyz')).toBeInTheDocument();
    expect(screen.getByText('def-456-uvw')).toBeInTheDocument();
  });

  it('renders section title and create button', () => {
    render(
      <ServiceAccountsSection
        accounts={[]}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    expect(screen.getByText('Service Accounts')).toBeInTheDocument();
    expect(screen.getByText('+ Create')).toBeInTheDocument();
  });

  it('opens create modal when create button is clicked', () => {
    render(
      <ServiceAccountsSection
        accounts={[]}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    fireEvent.click(screen.getByText('+ Create'));

    expect(screen.getByText('Create Service Account')).toBeInTheDocument();
  });

  it('calls onDelete when delete is confirmed', async () => {
    window.confirm = vi.fn().mockReturnValue(true);
    mockOnDelete.mockResolvedValue();

    render(
      <ServiceAccountsSection
        accounts={mockAccounts}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    const deleteButtons = screen.getAllByTitle('Delete service account');
    fireEvent.click(deleteButtons[0]);

    expect(window.confirm).toHaveBeenCalledWith(
      'Delete service account "my-pipeline"?\n\nThis will revoke all access for this account and cannot be undone.',
    );

    await waitFor(() => {
      expect(mockOnDelete).toHaveBeenCalledWith('abc-123-xyz');
    });
  });

  it('does not call onDelete when delete is cancelled', () => {
    window.confirm = vi.fn().mockReturnValue(false);

    render(
      <ServiceAccountsSection
        accounts={mockAccounts}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    const deleteButtons = screen.getAllByTitle('Delete service account');
    fireEvent.click(deleteButtons[0]);

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

  it('renders description text', () => {
    render(
      <ServiceAccountsSection
        accounts={[]}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    expect(
      screen.getByText(/Service accounts allow programmatic access/i),
    ).toBeInTheDocument();
  });

  it('shows table headers when accounts exist', () => {
    render(
      <ServiceAccountsSection
        accounts={mockAccounts}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    expect(screen.getByText('Name')).toBeInTheDocument();
    expect(screen.getByText('Client ID')).toBeInTheDocument();
    expect(screen.getByText('Created')).toBeInTheDocument();
  });

  it('handles delete error gracefully', async () => {
    const consoleSpy = vi.spyOn(console, 'error').mockImplementation();
    const alertSpy = vi.spyOn(window, 'alert').mockImplementation();
    window.confirm = vi.fn().mockReturnValue(true);
    mockOnDelete.mockRejectedValue(new Error('Delete failed'));

    render(
      <ServiceAccountsSection
        accounts={mockAccounts}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    const deleteButtons = screen.getAllByTitle('Delete service account');
    fireEvent.click(deleteButtons[0]);

    await waitFor(() => {
      expect(alertSpy).toHaveBeenCalledWith('Failed to delete service account');
    });

    consoleSpy.mockRestore();
    alertSpy.mockRestore();
  });

  it('closes modal when close button is clicked', () => {
    render(
      <ServiceAccountsSection
        accounts={[]}
        onCreate={mockOnCreate}
        onDelete={mockOnDelete}
      />,
    );

    // Open modal
    fireEvent.click(screen.getByText('+ Create'));
    expect(screen.getByText('Create Service Account')).toBeInTheDocument();

    // Close modal
    fireEvent.click(screen.getByTitle('Close'));

    // Modal should no longer be visible (it stays in DOM but should be hidden)
    // The modal content should be hidden
    expect(
      screen.queryByText('Create Service Account'),
    ).not.toBeInTheDocument();
  });
});
