import '@testing-library/jest-dom/vitest';
import { fireEvent, render, screen } from '@testing-library/svelte';
import { describe, expect, it, vi } from 'vitest';
import ServerLogin from './ServerLogin.svelte';

describe('ServerLogin', () => {
  it('renders server, account, and password fields', () => {
    render(ServerLogin, { props: { apiBase: 'http://localhost:8080' } });

    expect(screen.getByLabelText('Server IP or domain')).toBeInTheDocument();
    expect(screen.getByLabelText('Email or username')).toBeInTheDocument();
    expect(screen.getByLabelText('Password')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'Log in' })).toBeInTheDocument();
    expect(screen.getByRole('status')).toHaveTextContent('Not connected. Enter a server address to continue.');
  });

  it('normalizes server address and emits login details', async () => {
    const onLogin = vi.fn();
    render(ServerLogin, {
      props: {
        apiBase: 'localhost:8080',
        onLogin,
      },
    });

    await fireEvent.input(screen.getByLabelText('Server IP or domain'), {
      target: { value: '10.0.0.12:8080' },
    });
    await fireEvent.input(screen.getByLabelText('Email or username'), {
      target: { value: 'david@example.com' },
    });
    await fireEvent.input(screen.getByLabelText('Password'), {
      target: { value: 'secret' },
    });
    await fireEvent.click(screen.getByRole('button', { name: 'Log in' }));

    expect(onLogin).toHaveBeenCalledWith({
      apiBase: 'http://10.0.0.12:8080',
      account: 'david@example.com',
    });
  });

  it.each([
    ['localhost', 'http://localhost'],
    ['localhost:8080', 'http://localhost:8080'],
    ['192.168.1.20:3000', 'http://192.168.1.20:3000'],
    ['example.com:8443', 'http://example.com:8443'],
    ['https://example.com', 'https://example.com'],
  ])('accepts and normalizes a valid server value: %s', async (server, apiBase) => {
    const onLogin = vi.fn();
    render(ServerLogin, { props: { apiBase: 'http://localhost:8080', onLogin } });

    await fireEvent.input(screen.getByLabelText('Server IP or domain'), { target: { value: server } });
    await fireEvent.input(screen.getByLabelText('Email or username'), { target: { value: 'david@example.com' } });
    await fireEvent.input(screen.getByLabelText('Password'), { target: { value: 'secret' } });
    await fireEvent.click(screen.getByRole('button', { name: 'Log in' }));

    expect(onLogin).toHaveBeenCalledWith({ apiBase, account: 'david@example.com' });
  });

  it('shows an error when account or password is missing', async () => {
    render(ServerLogin, { props: { apiBase: 'http://localhost:8080' } });

    await fireEvent.click(screen.getByRole('button', { name: 'Log in' }));

    expect(screen.getByText('Enter an account and password.')).toBeInTheDocument();
  });

  it.each([
    ['', 'Enter a server address.'],
    ['http:// bad-server', 'Enter a valid HTTP or HTTPS server address.'],
    [' https://example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['https://example.com/path with spaces', 'Enter a valid HTTP or HTTPS server address.'],
    ['https://example%20.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['https://user:secret@example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http://', 'Enter a valid HTTP or HTTPS server address.'],
    ['ftp://example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http:////example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http//example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['https//example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http:/example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['https:/example.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http://example.com\\path', 'Enter a valid HTTP or HTTPS server address.'],
    ['example.com\\path', 'Enter a valid HTTP or HTTPS server address.'],
    ['http://example..com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http://-bad.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http://bad-.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http://bad_host.com', 'Enter a valid HTTP or HTTPS server address.'],
    ['http://bad!.com', 'Enter a valid HTTP or HTTPS server address.'],
  ])('rejects an invalid server value: %s', async (server, error) => {
    const onLogin = vi.fn();
    render(ServerLogin, { props: { apiBase: 'http://localhost:8080', onLogin } });

    await fireEvent.input(screen.getByLabelText('Server IP or domain'), { target: { value: server } });
    await fireEvent.input(screen.getByLabelText('Email or username'), { target: { value: 'david@example.com' } });
    await fireEvent.input(screen.getByLabelText('Password'), { target: { value: 'secret' } });
    await fireEvent.click(screen.getByRole('button', { name: 'Log in' }));

    expect(screen.getByText(error)).toBeInTheDocument();
    expect(onLogin).not.toHaveBeenCalled();
  });
});
