import { expect, Page } from '@playwright/test';

// Import the seed and switch to the user based on the ID.
// '01' -> user 111
// otherwise -> user 000
// (... which is a weird convention but I haven't taken the time to change it)
export async function importUser(page: Page, id?: string): Promise<string> {
  let seedPhrase, userName, did;

  // Set seed phrase and DID based on user ID
  switch(id) {
    case '01':
      seedPhrase = 'island fever beef wine urban aim vacant quit afford total poem flame service calm better adult neither color gaze forum month sister imitate excite';
      userName = 'User One';
      did = 'did:ethr:0x111d15564f824D56C7a07b913aA7aDd03382aA39';
      break;
    default: // to user 00
      seedPhrase = 'rigid shrug mobile smart veteran half all pond toilet brave review universe ship congress found yard skate elite apology jar uniform subway slender luggage';
      userName = 'User Zero';
      did = 'did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F';
  }

  // Import ID
  await page.goto('./start');
  await page.getByText('You have a seed').click();
  await page.getByPlaceholder('Seed Phrase').fill(seedPhrase);
  await page.getByRole('button', { name: 'Import' }).click();

  // Check DID
  await expect(page.getByRole('code')).toContainText(did);
  // ... and ensure the app retrieves the registration status
  await expect(page.locator('#sectionUsageLimits').getByText('Checking')).toBeHidden();
  return did;
}

export async function importUserAndCloseOnboarding(page: Page, id?: string): Promise<string> {
  const did = await importUser(page, id);
  await page.goto('./');
  await page.getByTestId('closeOnboardingAndFinish').click();
  return did;
}

// This is to switch to someone already in the identity table. It doesn't include registration.
export async function switchToUser(page: Page, did: string): Promise<void> {
  // This is the direct approach but users have to tap on things so we'll do that instead.
  //await page.goto('./identity-switcher');

  await page.goto('./account');
  await page.getByRole('heading', { name: 'Advanced' }).click();
  await page.getByRole('link', { name: 'Switch Identifier' }).click();
  const didElem = await page.locator(`code:has-text("${did}")`);
  await didElem.isVisible();
  await didElem.click();
  // wait for the switch to happen and the account page to fully load
  await page.getByTestId('didWrapper').locator('code:has-text("did:")');
}

function createContactName(did: string): string {
  return "User " + did.slice(11, 14);
}

export async function deleteContact(page: Page, did: string): Promise<void> {
  console.log('[DEBUG] deleteContact: Starting deletion for DID:', did);
  
  await page.goto('./contacts');
  console.log('[DEBUG] deleteContact: Navigated to contacts page');
  
  // Wait for the page to load completely
  await page.waitForLoadState('networkidle');
  console.log('[DEBUG] deleteContact: Page load completed');
  
  // Check if there are any loading indicators or filters active
  const loadingIndicator = page.locator('[data-testid*="loading"], .loading, .spinner');
  const loadingCount = await loadingIndicator.count();
  console.log('[DEBUG] deleteContact: Loading indicators found:', loadingCount);
  
  // Check for any filter or state buttons that might be active
  const showGiveNumbers = page.locator('button:has-text("Hide Actions")');
  const showGiveNumbersExists = await showGiveNumbers.count();
  console.log('[DEBUG] deleteContact: "Hide Actions" button exists (showing give numbers):', showGiveNumbersExists > 0);
  
  if (showGiveNumbersExists > 0) {
    console.log('[DEBUG] deleteContact: Clicking "Hide Actions" to show normal view');
    await showGiveNumbers.click();
    await page.waitForTimeout(1000); // Wait for UI to update
  }
  
  const contactName = createContactName(did);
  console.log('[DEBUG] deleteContact: Looking for contact with name:', contactName);
  
  // First, let's see what contacts are actually on the page
  const contactItems = await page.locator('li[data-testid="contactListItem"]');
  const contactCount = await contactItems.count();
  console.log('[DEBUG] deleteContact: Found contact items on page:', contactCount);
  
  // Log all contact names visible on the page
  for (let i = 0; i < contactCount; i++) {
    const contactItem = contactItems.nth(i);
    const nameElement = contactItem.locator('h2');
    const nameText = await nameElement.textContent();
    console.log('[DEBUG] deleteContact: Contact', i, ':', nameText);
  }
  
  // If no contacts found, let's take a screenshot to see what's on the page
  if (contactCount === 0) {
    console.log('[DEBUG] deleteContact: No contacts found, taking screenshot');
    await page.screenshot({ path: 'debug-no-contacts.png', fullPage: true });
    console.log('[DEBUG] deleteContact: Screenshot saved as debug-no-contacts.png');
  }
  
  // Try to find the contact list item with the expected name
  const contactListItem = page.locator(`li[data-testid="contactListItem"]:has(h2:has-text("${contactName}"))`);
  const contactExists = await contactListItem.count();
  console.log('[DEBUG] deleteContact: Contact with name exists:', contactName, contactExists > 0);
  
  if (contactExists === 0) {
    console.error('[DEBUG] deleteContact: Contact not found on page:', contactName);
    throw new Error(`Contact "${contactName}" not found on contacts page`);
  }
  
  // Now click the info icon - fix the selector to match actual DOM structure
  // Try different selectors for the info icon
  const infoIconSelectors = [
    `li[data-testid="contactListItem"]:has(h2:has-text("${contactName}")) font-awesome[icon="circle-info"]`,
    `li[data-testid="contactListItem"]:has(h2:has-text("${contactName}")) .fa-circle-info`,
    `li[data-testid="contactListItem"]:has(h2:has-text("${contactName}")) svg.fa-circle-info`,
    `li[data-testid="contactListItem"]:has(h2:has-text("${contactName}")) [class*="fa-circle-info"]`
  ];
  
  let infoIcon: import('@playwright/test').Locator | null = null;
  let infoIconExists = 0;
  
  for (const selector of infoIconSelectors) {
    console.log('[DEBUG] deleteContact: Trying selector:', selector);
    const testIcon = page.locator(selector);
    const testCount = await testIcon.count();
    console.log('[DEBUG] deleteContact: Selector result count:', testCount);
    
    if (testCount > 0) {
      infoIcon = testIcon;
      infoIconExists = testCount;
      console.log('[DEBUG] deleteContact: Found working selector:', selector);
      break;
    }
  }
  
  console.log('[DEBUG] deleteContact: Info icon exists:', infoIconExists > 0);
  
  if (infoIconExists === 0 || !infoIcon) {
    console.error('[DEBUG] deleteContact: Info icon not found for contact:', contactName);
    throw new Error(`Info icon not found for contact "${contactName}"`);
  }
  
  // go to the detail page for this contact
  await infoIcon.click();
  console.log('[DEBUG] deleteContact: Clicked info icon, should be on detail page');
  
  // Verify we're on the detail page
  const detailPageHeading = page.locator('h1:has-text("Identifier Details")');
  await detailPageHeading.waitFor({ timeout: 10000 });
  console.log('[DEBUG] deleteContact: Confirmed on detail page');
  
  // delete the contact
  const deleteButton = page.locator('button > svg.fa-trash-can');
  const deleteButtonExists = await deleteButton.count();
  console.log('[DEBUG] deleteContact: Delete button exists:', deleteButtonExists > 0);
  
  if (deleteButtonExists === 0) {
    console.error('[DEBUG] deleteContact: Delete button not found');
    throw new Error('Delete button not found on detail page');
  }
  
  await deleteButton.click();
  console.log('[DEBUG] deleteContact: Clicked delete button');
  
  // Confirm deletion
  const confirmButton = page.locator('div[role="alert"] button:has-text("Yes")');
  await confirmButton.waitFor({ timeout: 10000 });
  console.log('[DEBUG] deleteContact: Confirmation dialog appeared');
  
  await confirmButton.click();
  console.log('[DEBUG] deleteContact: Clicked confirmation button');
  
  // for some reason, .isHidden() (without expect) doesn't work
  await expect(page.locator('div[role="alert"] button:has-text("Yes")')).toBeHidden();
  console.log('[DEBUG] deleteContact: Confirmation dialog dismissed, deletion complete');
}

export async function generateNewEthrUser(page: Page): Promise<string> {
  await page.goto('./start');
  await page.getByTestId('newSeed').click();
  await expect(page.locator('span:has-text("Created")')).toBeVisible();

  await page.goto('./account');
  const didElem = await page.getByTestId('didWrapper').locator('code:has-text("did:")');
  const newDid = await didElem.innerText();
  return newDid;
}

// Generate a new random user and register them.
// Note that this makes 000 the active user. Use switchToUser to switch to this DID.
export async function generateAndRegisterEthrUser(page: Page): Promise<string> {
  console.log('[DEBUG] generateAndRegisterEthrUser: Starting user generation');
  const newDid = await generateNewEthrUser(page);
  console.log('[DEBUG] generateAndRegisterEthrUser: Generated new DID:', newDid);

  await importUser(page, '000'); // switch to user 000
  console.log('[DEBUG] generateAndRegisterEthrUser: Switched to user 000');

  await page.goto('./contacts');
  console.log('[DEBUG] generateAndRegisterEthrUser: Navigated to contacts page');
  
  const contactName = createContactName(newDid);
  console.log('[DEBUG] generateAndRegisterEthrUser: Created contact name:', contactName);
  
  const contactInput = `${newDid}, ${contactName}`;
  console.log('[DEBUG] generateAndRegisterEthrUser: Filling contact input with:', contactInput);
  
  await page.getByPlaceholder('URL or DID, Name, Public Key').fill(contactInput);
  await page.locator('button > svg.fa-plus').click();
  console.log('[DEBUG] generateAndRegisterEthrUser: Clicked add contact button');
  
  // register them
  await page.locator('div[role="alert"] button:has-text("Yes")').click();
  console.log('[DEBUG] generateAndRegisterEthrUser: Clicked registration confirmation');
  
  // wait for it to disappear because the next steps may depend on alerts being gone
  await expect(page.locator('div[role="alert"] button:has-text("Yes")')).toBeHidden();
  console.log('[DEBUG] generateAndRegisterEthrUser: Registration dialog dismissed');
  
  await expect(page.locator('li', { hasText: contactName })).toBeVisible();
  console.log('[DEBUG] generateAndRegisterEthrUser: Contact is now visible in list:', contactName);

  return newDid;
}

// Function to generate a random string of specified length
export async function generateRandomString(length: number): Promise<string> {
  return Math.random().toString(36).substring(2, 2 + length);
}

// Function to create an array of unique strings
export async function createUniqueStringsArray(count: number): Promise<string[]> {
  const stringsArray: string[] = [];
  const stringLength = 16;

  for (let i = 0; i < count; i++) {
    let randomString = await generateRandomString(stringLength);
    stringsArray.push(randomString);
  }

  return stringsArray;
}

// Function to create an array of two-digit non-zero numbers
export async function createRandomNumbersArray(count: number): Promise<number[]> {
  const numbersArray: number[] = [];

  for (let i = 0; i < count; i++) {
    let randomNumber = Math.floor(Math.random() * 99) + 1;
    numbersArray.push(randomNumber);
  }

  return numbersArray;
}

export function isLinuxEnvironment() {
    return process.platform === 'linux';
}

export function getOSSpecificTimeout(): number {
  // Increase base timeout for Linux
  const isLinux = process.platform === 'linux';
  return isLinux ? 180000 : 60000; // 3 minutes for Linux, 1 minute for others
}

export function getOSSpecificConfig() {
    if (isLinuxEnvironment()) {
        return {
            retries: 2,
            timeout: 90000,  // Increased global timeout
            expect: {
                timeout: 30000  // Increased expect timeout
            },
            // Add video recording for failed tests on Linux
            use: {
                video: 'retain-on-failure',
                trace: 'retain-on-failure'
            }
        };
    }
    return {};
}

// Add helper for test grouping
export function isResourceIntensiveTest(testPath: string): boolean {
    return testPath.includes('35-record-gift-from-image-share') || 
           testPath.includes('40-add-contact');
}
