/**
 * @fileoverview Tests for the new activity/offers system in TimeSafari
 * 
 * CRITICAL UNDERSTANDING: Offer Acknowledgment System
 * ===================================================
 * 
 * This file tests the offer acknowledgment mechanism, which was clarified through
 * systematic debugging investigation. Key findings:
 * 
 * 1. POINTER-BASED TRACKING:
 *    - TimeSafari uses `lastAckedOfferToUserJwtId` to track the last acknowledged offer
 *    - Offers with IDs newer than this pointer are considered "new" and counted
 *    - The UI shows count of offers newer than the pointer
 * 
 * 2. TWO DISMISSAL MECHANISMS:
 *    a) COMPLETE DISMISSAL (used in this test):
 *       - Triggered by: Expanding offers section (clicking chevron)
 *       - Method: expandOffersToUserAndMarkRead()
 *       - Action: Sets lastAckedOfferToUserJwtId = newOffersToUser[0].jwtId (newest)
 *       - Result: ALL offers marked as read, count becomes 0 (hidden)
 * 
 *    b) SELECTIVE DISMISSAL:
 *       - Triggered by: Clicking "Keep all above as new offers"
 *       - Method: markOffersAsReadStartingWith(jwtId)
 *       - Action: Sets lastAckedOfferToUserJwtId = nextOffer.jwtId (partial)
 *       - Result: Only offers above clicked offer marked as read
 * 
 * 3. BROWSER COMPATIBILITY:
 *    - Initially appeared to be Chromium-specific issue
 *    - Investigation revealed test logic error, not browser incompatibility
 *    - Both Chromium and Firefox now pass consistently
 * 
 * @author Matthew Raymer
 * @since Investigation completed 2024-12-27
 */

import { test, expect } from '@playwright/test';
import { importUser, generateNewEthrUser, switchToUser } from './testUtils';

test('New offers for another user', async ({ page }) => {
  const user01Did = await generateNewEthrUser(page);
  await page.goto('./');
  await page.getByTestId('closeOnboardingAndFinish').click();
  await expect(page.getByTestId('newDirectOffersActivityNumber')).toBeHidden();

  await importUser(page, '00');
  await page.goto('./contacts');
  await page.getByPlaceholder('URL or DID, Name, Public Key').fill(user01Did + ', A Friend');
  await expect(page.locator('button > svg.fa-plus')).toBeVisible();
  await page.locator('button > svg.fa-plus').click();
  await expect(page.locator('div[role="alert"] span:has-text("Contact Added")')).toBeVisible();
  await page.locator('div[role="alert"] button:has-text("No")').click(); // don't register
  await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
  await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone

  // show buttons to make offers directly to people
  await page.getByRole('button').filter({ hasText: /See Actions/i }).click();

  // make an offer directly to user 1
  // Generate a random string of 3 characters, skipping the "0." at the beginning
  const randomString1 = Math.random().toString(36).substring(2, 5);
  await page.getByTestId('offerButton').click();
  await page.getByTestId('inputDescription').fill(`help of ${randomString1} from #000`);
  await page.getByTestId('inputOfferAmount').fill('1');
  await page.getByRole('button', { name: 'Sign & Send' }).click();
  await expect(page.getByText('That offer was recorded.')).toBeVisible();
  await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
  await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone

  // make another offer to user 1
  const randomString2 = Math.random().toString(36).substring(2, 5);
  await page.getByTestId('offerButton').click();
  await page.getByTestId('inputDescription').fill(`help of ${randomString2} from #000`);
  await page.getByTestId('inputOfferAmount').fill('3');
  await page.getByRole('button', { name: 'Sign & Send' }).click();
  await expect(page.getByText('That offer was recorded.')).toBeVisible();
  await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
  await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone

  // as user 1, go to the home page and check that two offers are shown as new
  await switchToUser(page, user01Did);
  await page.goto('./');
  await page.waitForLoadState('networkidle');
  
  let offerNumElemForTest = page.getByTestId('newDirectOffersActivityNumber');
  await expect(offerNumElemForTest).toHaveText('2');

  // click on the number of new offers to go to the list page
  await offerNumElemForTest.click();

  await expect(page.getByText('New Offers To You', { exact: true })).toBeVisible();
  await page.getByTestId('showOffersToUser').locator('div > svg.fa-chevron-right').click();
  // note that they show in reverse chronologicalorder
  await expect(page.getByText(`help of ${randomString2} from #000`)).toBeVisible();
  await expect(page.getByText(`help of ${randomString1} from #000`)).toBeVisible();

  /**
   * OFFER ACKNOWLEDGMENT MECHANISM:
   * 
   * TimeSafari uses a pointer-based system to track which offers are "new":
   * - `lastAckedOfferToUserJwtId` stores the ID of the last acknowledged offer
   * - Offers newer than this pointer are considered "new" and counted
   * 
   * Two dismissal mechanisms exist:
   * 1. COMPLETE DISMISSAL: Expanding the offers section calls expandOffersToUserAndMarkRead()
   *    which sets lastAckedOfferToUserJwtId = newOffersToUser[0].jwtId (newest offer)
   *    Result: ALL offers marked as read, count goes to 0
   * 
   * 2. SELECTIVE DISMISSAL: "Keep all above" calls markOffersAsReadStartingWith(jwtId)
   *    which sets lastAckedOfferToUserJwtId = nextOffer.jwtId (partial dismissal)
   *    Result: Only offers above the clicked offer are marked as read
   * 
   * This test uses mechanism #1 (expansion) for complete dismissal.
   * The expansion already happened when we clicked the chevron above.
   */

  // now see that all offers are dismissed since we expanded the section
  await page.goto('./');
  await page.waitForLoadState('networkidle');

  // wait until the list with ID listLatestActivity has at least one visible item
  await page.locator('#listLatestActivity li').first().waitFor({ state: 'visible' });
  
  await expect(page.getByTestId('newDirectOffersActivityNumber')).toBeHidden();
});
