import { expect } from '@playwright/test';
import { test } from '../../fixtures/multi-client';
import { openSettingsFromMenu } from '../../helpers/app-menu';
import { expectDashboardReady } from '../../helpers/dashboard';
import { installTestServerEndpoints } from '../../helpers/seed-test-endpoint';
import { startTestServer } from '../../helpers/test-server';
import {
  readAuthTokenFromPage,
  readSignalServerCredentialFromPage,
  registerTestUser
} from '../../helpers/auth-api';
import { RegisterPage } from '../../pages/register.page';

const PRIMARY_ENDPOINT_ID = 'e2e-multi-auth-primary';
const USER_PASSWORD = 'TestPass123!';

test.describe('Multi-signal-server authentication', () => {
  test.describe.configure({ timeout: 180_000 });

  test('auto-provisions a foreign signal server when a new endpoint is added', async ({ createClient, request }) => {
    const primaryServer = await startTestServer();
    const secondaryServer = await startTestServer();

    try {
      const client = await createClient();
      const suffix = `multi_auth_${Date.now()}`;
      const username = `user_${suffix}`;

      await installTestServerEndpoints(client.context, [
        {
          id: PRIMARY_ENDPOINT_ID,
          name: 'E2E Primary Signal',
          url: primaryServer.url,
          isActive: true,
          status: 'online'
        }
      ]);

      await test.step('Register on the home signal server', async () => {
        const register = new RegisterPage(client.page);

        await register.goto();
        await register.register(username, 'Multi Auth User', USER_PASSWORD);
        await expectDashboardReady(client.page);
      });

      await test.step('Add a second signal server in network settings', async () => {
        await openSettingsFromMenu(client.page);
        await client.page.getByRole('button', { name: 'Network' }).click();

        await client.page.getByPlaceholder('Server name').fill('E2E Secondary Signal');
        await client.page.getByPlaceholder('Server URL (e.g., http://localhost:3001)').fill(secondaryServer.url);
        await client.page.getByTestId('add-signal-server-button').click();

        await expect(client.page.getByText(secondaryServer.url)).toBeVisible({ timeout: 15_000 });
      });

      await test.step('Wait for auto-provisioned credentials on the secondary server', async () => {
        await expect.poll(async () =>
          await readSignalServerCredentialFromPage(client.page, secondaryServer.url),
        { timeout: 30_000 }
        ).not.toBeNull();

        const homeToken = await readAuthTokenFromPage(client.page, primaryServer.url);
        const secondaryCredential = await readSignalServerCredentialFromPage(client.page, secondaryServer.url);

        expect(homeToken).toBeTruthy();
        expect(secondaryCredential?.username).toBe(username);
        expect(secondaryCredential?.token).toBeTruthy();
      });

      await test.step('Secondary credential can call authenticated APIs', async () => {
        const secondaryCredential = await readSignalServerCredentialFromPage(client.page, secondaryServer.url);

        if (!secondaryCredential) {
          throw new Error('Expected secondary signal-server credential to be provisioned');
        }

        const response = await request.post(`${secondaryServer.url}/api/servers`, {
          headers: {
            Authorization: `Bearer ${secondaryCredential.token}`,
            'Content-Type': 'application/json'
          },
          data: {
            name: `Secondary Provisioned Server ${suffix}`,
            description: 'Created with auto-provisioned credentials',
            ownerId: secondaryCredential.userId,
            ownerPublicKey: 'e2e-secondary-owner-key'
          }
        });

        expect(response.ok(), `POST /api/servers failed: ${response.status()} ${await response.text()}`).toBe(true);
      });

      await test.step('Home registration still works independently on the secondary server', async () => {
        const otherUser = await registerTestUser(
          request,
          secondaryServer.url,
          `other_${suffix}`,
          USER_PASSWORD,
          'Other User'
        );

        expect(otherUser.username).toBe(`other_${suffix}`);
      });
    } finally {
      await primaryServer.stop();
      await secondaryServer.stop();
    }
  });
});
