/**
 * Initial State and Basic Functionality Tests
 * 
 * Core test suite that validates fundamental application features and initial state handling.
 * These tests run first to ensure basic functionality before more complex tests.
 * 
 * Test Categories:
 * 1. Activity Feed
 *    - Verifies server connectivity
 *    - Tests infinite scroll loading
 *    - Checks initial 10 activities load
 *    - Validates additional activity loading
 * 
 * 2. Discovery Features
 *    - Tests project listing
 *    - Verifies infinite scroll
 *    - Checks project card rendering
 * 
 * 3. Account State
 *    - Validates initial no-ID state
 *    - Tests ID generation flow
 *    - Verifies registration notices
 *    - Checks account detail display
 * 
 * 4. Contact Sharing
 *    - Tests name setting functionality
 *    - Validates clipboard operations
 *    - Checks sharing UI elements
 *    - Verifies alert handling
 * 
 * 5. User Registration
 *    - Tests User 0's ability to register others
 *    - Validates gift recording after registration
 *    - Checks contact deletion
 *    - Verifies deleted contact handling
 * 
 * Key Selectors:
 * - Activity list: 'ul#listLatestActivity li'
 * - Discover list: 'ul#listDiscoverResults li'
 * - Account notices: '#noticeBeforeShare', '#noticeBeforeAnnounce'
 * - Identity details: '#sectionIdentityDetails code.truncate'
 * 
 * State Verification:
 * - Checks empty ID state
 * - Verifies ID generation
 * - Validates alert presence/dismissal
 * - Confirms navigation state
 * 
 * Alert Handling:
 * - Closes onboarding dialogs
 * - Verifies alert content
 * - Checks alert dismissal
 * - Validates alert transitions
 * 
 * Important Checks:
 * - Server connectivity
 * - Data loading
 * - UI state transitions
 * - Error conditions
 * - Clipboard operations
 * 
 * @example Checking activity feed
 * ```typescript
 * await page.goto('./');
 * await page.getByTestId('closeOnboardingAndFinish').click();
 * await expect(page.locator('ul#listLatestActivity li:nth-child(10)'))
 *   .toBeVisible();
 * ```
 */

import { test, expect } from '@playwright/test';
import { deleteContact, generateAndRegisterEthrUser, importUser } from './testUtils';

test('Check activity feed - check that server is running', async ({ page }) => {
  // Load app homepage
  await page.goto('./');
  await page.getByTestId('closeOnboardingAndFinish').click();

  // Check that initial 10 activities have been loaded
  await expect(page.locator('ul#listLatestActivity li:nth-child(10)')).toBeVisible();

  // Scroll down a bit to trigger loading additional activities
  await page.locator('ul#listLatestActivity li:nth-child(50)').scrollIntoViewIfNeeded();
});

test('Check discover results', async ({ page }) => {
  // Load Discover view
  await page.goto('./discover');

  // Check that initial 10 projects have been loaded
  await expect(page.locator('ul#listDiscoverResults li.border-b:nth-child(10)')).toBeVisible();

  // Scroll down a bit to trigger loading additional projects
  await page.locator('ul#listDiscoverResults li.border-b:nth-child(20)').scrollIntoViewIfNeeded();
});

test('Check no-ID messaging in account', async ({ page }) => {
  // Load account view
  await page.goto('./account');

  // Check 'someone must register you' notice
  await expect(page.locator('#noticeBeforeShare')).toBeVisible();

  // Check 'a friend needs to register you' notice
  await expect(page.locator('#noticeBeforeAnnounce')).toBeVisible();

  // Check that there is no ID
  await expect(page.locator('#sectionIdentityDetails code.truncate')).toBeEmpty();
});

test('Check ability to share contact', async ({ page }) => {
  // Load Discover view
  await page.goto('./discover');

  // Check that initial 10 projects have been loaded
  await expect(page.locator('ul#listDiscoverResults li.border-b:nth-child(10)')).toBeVisible();

  // Scroll down a bit to trigger loading additional projects
  await page.locator('ul#listDiscoverResults li.border-b:nth-child(20)').scrollIntoViewIfNeeded();
});

test('Check ID generation', async ({ page }) => {
  // Load Account view
  await page.goto('./account');

  // Check that ID is empty
  await expect(page.locator('#sectionIdentityDetails code.truncate')).toBeEmpty();

  // Load homepage to trigger ID generation (?)
  await page.goto('./');

  // Wait for activity feed to start loading, as a delay
  await expect(page.locator('ul#listLatestActivity li:nth-child(10)')).toBeVisible();

  // Check 'someone must register you' notice
  await expect(page.getByText('To share, someone must register you.')).toBeVisible();

  // Go back to Account view
  await page.goto('./account');

  // Check that ID is now generated
  await expect(page.locator('#sectionIdentityDetails code.truncate')).toContainText('did:ethr:');
});


test('Check setting name & sharing info', async ({ page }) => {
  // Load homepage to trigger ID generation (?)
  await page.goto('./');
  await page.getByTestId('closeOnboardingAndFinish').click();
  // Check 'someone must register you' notice
  await expect(page.getByText('someone must register you.')).toBeVisible();
  await page.getByRole('button', { name: /Show them/}).click();
  // fill in a name
  await expect(page.getByText('Set Your Name')).toBeVisible();
  await page.getByRole('textbox').fill('Me Test User');
  await page.locator('button:has-text("Save")').click();
  await expect(page.getByText('share some other way')).toBeVisible();
  await page.getByRole('button', { name: /share some other way/ }).click();
  await expect(page.getByRole('button', { name: 'copy to clipboard' })).toBeVisible();
  await page.getByRole('button', { name: 'copy to clipboard' }).click();
  await expect(page.getByText('contact info was copied')).toBeVisible();
  // dismiss alert and wait for it to go away
  await page.locator('div[role="alert"] button > svg.fa-xmark').click();
  await expect(page.getByText('contact info was copied')).toBeHidden();
  // check that they're on the Contacts screen
  await expect(page.getByText('your contacts')).toBeVisible();
});

test('Confirm test API setting (may fail if you are running your own Time Safari)', async ({ page }, testInfo) => {
  // Load account view
  await page.goto('./account');
  await page.getByRole('heading', { name: 'Advanced' }).click();

  // look into the config file: if it starts Time Safari, it might say which server it should set by default
  const webServer = testInfo.config.webServer;
  const endorserWords = webServer?.command.split(' ');
  const ENDORSER_ENV_NAME = 'VITE_DEFAULT_ENDORSER_API_SERVER';
  const endorserTerm = endorserWords?.find(word => word.startsWith(ENDORSER_ENV_NAME + '='));
  const endorserTermInConfig = endorserTerm?.substring(ENDORSER_ENV_NAME.length + 1);

  const endorserServer = endorserTermInConfig || 'https://test-api.endorser.ch';
  await expect(page.locator('#apiServerInput')).toHaveValue(endorserServer);
});

test('Check User 0 can register a random person', async ({ page }) => {
  await importUser(page, '00');
  const newDid = await generateAndRegisterEthrUser(page);
  expect(newDid).toContain('did:ethr:');

  await page.goto('./');
  await page.getByTestId('closeOnboardingAndFinish').click();
  await page.getByRole('heading', { name: 'Unnamed/Unknown' }).click();
  await page.getByPlaceholder('What was given').fill('Gave me access!');
  await page.getByRole('button', { name: 'Sign & Send' }).click();
  await expect(page.getByText('That gift was recorded.')).toBeVisible();
  // now ensure that alert goes away
  await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss alert
  await expect(page.getByText('That gift was recorded.')).toBeHidden();

  // now delete the contact to test that pages still do reasonable things
  await deleteContact(page, newDid);
  // go the activity page for this new person
  await page.goto('./did/' + encodeURIComponent(newDid));
  // maybe replace by: const popupPromise = page.waitForEvent('popup');
  let error;
  try {
    await page.waitForSelector('div[role="alert"]', { timeout: 2000 });
    error = new Error('Error alert should not show.');
  } catch (error) {
    // success
  } finally {
    if (error) {
      throw error;
    }
  }
});
