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

const mockAccounts = [
  { id: 'acc_1', jid: '111@s.whatsapp.net', displayName: 'Account One', status: 'ACTIVE', platform: 'whatsapp' },
  { id: 'acc_2', jid: '222@s.whatsapp.net', displayName: null, status: 'DISCONNECTED', platform: 'whatsapp' },
];

let fetchSpy: jest.SpyInstance;

beforeEach(() => {
  fetchSpy = jest.spyOn(global, 'fetch');
});

afterEach(() => {
  jest.restoreAllMocks();
});

describe('AccountsList', () => {
  it('renders an AccountCard for each initial account', () => {
    render(<AccountsList initialAccounts={mockAccounts} />);
    expect(screen.getByText('Account One')).toBeInTheDocument();
    expect(screen.getByText('222@s.whatsapp.net')).toBeInTheDocument();
  });

  it('shows empty state when no accounts', () => {
    render(<AccountsList initialAccounts={[]} />);
    expect(screen.getByText(/no accounts yet/i)).toBeInTheDocument();
  });

  it('renders Add Account button', () => {
    render(<AccountsList initialAccounts={[]} />);
    expect(screen.getByRole('button', { name: /add account/i })).toBeInTheDocument();
  });

  it('renders display name input', () => {
    render(<AccountsList initialAccounts={[]} />);
    expect(screen.getByPlaceholderText(/display name/i)).toBeInTheDocument();
  });

  it('calls POST /api/accounts when Add Account is clicked', async () => {
    fetchSpy.mockResolvedValue(
      new Response(
        JSON.stringify({ id: 'acc_new', jid: 'pending_x@placeholder', displayName: null, status: 'ACTIVE', platform: 'whatsapp' }),
        { status: 201, headers: { 'Content-Type': 'application/json' } },
      ),
    );
    render(<AccountsList initialAccounts={[]} />);
    fireEvent.click(screen.getByRole('button', { name: /add account/i }));
    await waitFor(() =>
      expect(fetchSpy).toHaveBeenCalledWith('/api/accounts', expect.objectContaining({ method: 'POST' })),
    );
  });

  it('adds new account to list after successful POST', async () => {
    const newAccount = { id: 'acc_new', jid: 'pending_x@placeholder', displayName: 'New Device', status: 'ACTIVE', platform: 'whatsapp' };
    fetchSpy.mockResolvedValue(
      new Response(JSON.stringify(newAccount), {
        status: 201,
        headers: { 'Content-Type': 'application/json' },
      }),
    );
    render(<AccountsList initialAccounts={[]} />);
    const input = screen.getByPlaceholderText(/display name/i);
    fireEvent.change(input, { target: { value: 'New Device' } });
    fireEvent.click(screen.getByRole('button', { name: /add account/i }));
    await waitFor(() => expect(screen.getByText('New Device')).toBeInTheDocument());
  });

  it('sends displayName in POST body when entered', async () => {
    fetchSpy.mockResolvedValue(
      new Response(
        JSON.stringify({ id: 'acc_new', jid: 'pending_x@placeholder', displayName: 'Test Name', status: 'ACTIVE', platform: 'whatsapp' }),
        { status: 201, headers: { 'Content-Type': 'application/json' } },
      ),
    );
    render(<AccountsList initialAccounts={[]} />);
    const input = screen.getByPlaceholderText(/display name/i);
    fireEvent.change(input, { target: { value: 'Test Name' } });
    fireEvent.click(screen.getByRole('button', { name: /add account/i }));
    await waitFor(() =>
      expect(fetchSpy).toHaveBeenCalledWith(
        '/api/accounts',
        expect.objectContaining({
          body: JSON.stringify({ displayName: 'Test Name' }),
        }),
      ),
    );
  });

  it('clears the input after successful account creation', async () => {
    fetchSpy.mockResolvedValue(
      new Response(
        JSON.stringify({ id: 'acc_new', jid: 'pending_x@placeholder', displayName: null, status: 'ACTIVE', platform: 'whatsapp' }),
        { status: 201, headers: { 'Content-Type': 'application/json' } },
      ),
    );
    render(<AccountsList initialAccounts={[]} />);
    const input = screen.getByPlaceholderText(/display name/i) as HTMLInputElement;
    fireEvent.change(input, { target: { value: 'My Device' } });
    fireEvent.click(screen.getByRole('button', { name: /add account/i }));
    await waitFor(() => expect(input.value).toBe(''));
  });
});
