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

export interface LoginCredentials {
  email: string;
  password: string;
}

export interface SessionFormData {
  sessionName?: string;
  sessionType?: 'private' | 'public' | 'friends';
  description?: string;
}

/**
 * Login to jam-ui application
 */
export async function loginToJamUI(
  page: Page,
  credentials: LoginCredentials = {
    email: 'nuwan@jamkazam.com',
    password: 'jam123',
  }
): Promise<void> {
  await page.goto('http://beta.jamkazam.local:4000/');

  // Wait for login form to be visible
  await page.waitForSelector('input[name="email"], input[type="email"], #email', {
    timeout: 10000,
  });

  // Fill in credentials - try multiple selectors
  const emailSelectors = ['input[name="email"]', 'input[type="email"]', '#email', '[placeholder*="email" i]'];
  for (const selector of emailSelectors) {
    try {
      const element = await page.$(selector);
      if (element) {
        await page.fill(selector, credentials.email);
        break;
      }
    } catch {
      continue;
    }
  }

  const passwordSelectors = ['input[name="password"]', 'input[type="password"]', '#password'];
  for (const selector of passwordSelectors) {
    try {
      const element = await page.$(selector);
      if (element) {
        await page.fill(selector, credentials.password);
        break;
      }
    } catch {
      continue;
    }
  }

  // Submit form
  const submitSelectors = [
    'button[type="submit"]',
    'input[type="submit"]',
    'button:has-text("Sign In")',
    'button:has-text("Login")',
  ];
  for (const selector of submitSelectors) {
    try {
      const element = await page.$(selector);
      if (element) {
        await page.click(selector);
        break;
      }
    } catch {
      continue;
    }
  }

  // Wait for navigation after login
  await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {});
  await page.waitForTimeout(2000);
}

/**
 * Navigate to session creation page
 */
export async function navigateToSessionCreation(page: Page): Promise<void> {
  // Try multiple selectors for the create session link
  const createSessionSelectors = [
    'text=create session',
    'text=Create Session',
    'a:has-text("create session")',
    'a:has-text("Create Session")',
    '[href*="session"][href*="create"]',
    '[data-testid="create-session"]',
  ];

  let clicked = false;
  for (const selector of createSessionSelectors) {
    try {
      const element = await page.$(selector);
      if (element) {
        await page.click(selector);
        clicked = true;
        break;
      }
    } catch {
      continue;
    }
  }

  if (!clicked) {
    throw new Error('Could not find "Create Session" link');
  }

  await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {});
  await page.waitForTimeout(1000);
}

/**
 * Fill and submit session creation form (jam-ui uses form-based creation)
 */
export async function fillSessionForm(page: Page, formData: SessionFormData = {}): Promise<void> {
  const {
    sessionName = 'Test Session ' + Date.now(),
    sessionType = 'private',
    description = 'Automated test session',
  } = formData;

  console.log('Filling session creation form...');

  // Wait for form to be visible
  await page.waitForTimeout(1000);

  // Fill session name - try multiple selectors
  const nameSelectors = [
    'input[name="session_name"]',
    'input[name="name"]',
    'input[name="sessionName"]',
    '#session_name',
    '#name',
    '#sessionName',
    'input[placeholder*="name" i]',
  ];

  let nameFilled = false;
  for (const selector of nameSelectors) {
    try {
      const element = await page.$(selector);
      if (element && await element.isVisible()) {
        await page.fill(selector, sessionName);
        console.log(`  Filled session name using: ${selector}`);
        nameFilled = true;
        break;
      }
    } catch {
      continue;
    }
  }

  if (!nameFilled) {
    console.log('  Warning: Could not find session name field');
  }

  // Select session type if there's a dropdown
  const typeSelectors = [
    'select[name="session_type"]',
    'select[name="type"]',
    'select[name="sessionType"]',
    '#session_type',
    '#type',
    '#sessionType',
  ];

  for (const selector of typeSelectors) {
    try {
      const element = await page.$(selector);
      if (element && await element.isVisible()) {
        await page.selectOption(selector, sessionType);
        console.log(`  Selected session type: ${sessionType}`);
        break;
      }
    } catch {
      continue;
    }
  }

  // Try clicking radio buttons for session type
  const radioSelectors = [
    `input[type="radio"][value="${sessionType}"]`,
    `input[type="radio"][id*="${sessionType}" i]`,
    `label:has-text("${sessionType}") input[type="radio"]`,
  ];

  for (const selector of radioSelectors) {
    try {
      const element = await page.$(selector);
      if (element && await element.isVisible()) {
        await page.click(selector);
        console.log(`  Clicked radio for: ${sessionType}`);
        break;
      }
    } catch {
      continue;
    }
  }

  // Fill description if field exists
  const descSelectors = [
    'textarea[name="description"]',
    'input[name="description"]',
    'textarea[name="notes"]',
    '#description',
    '#notes',
  ];

  for (const selector of descSelectors) {
    try {
      const element = await page.$(selector);
      if (element && await element.isVisible()) {
        await page.fill(selector, description);
        console.log(`  Filled description`);
        break;
      }
    } catch {
      continue;
    }
  }

  await page.waitForTimeout(500);

  // Submit form
  console.log('Submitting form...');
  const submitSelectors = [
    'button[type="submit"]',
    'input[type="submit"]',
    'button:has-text("Create Session")',
    'button:has-text("Create")',
    'button:has-text("Submit")',
    'button:has-text("Start Session")',
  ];

  let submitted = false;
  for (const selector of submitSelectors) {
    try {
      const element = await page.$(selector);
      if (element && await element.isVisible()) {
        await page.click(selector);
        console.log(`  Clicked submit button: ${selector}`);
        submitted = true;
        break;
      }
    } catch {
      continue;
    }
  }

  if (!submitted) {
    throw new Error('Could not find submit button for session creation form');
  }

  await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {});
  await page.waitForTimeout(3000);

  console.log('Form submitted, waiting for session to load...');
}

/**
 * Create and join session using jam-ui's form-based approach
 * (jam-ui doesn't have Quick Start buttons - it uses a form)
 */
export async function createAndJoinSession(
  page: Page,
  sessionData: SessionFormData = {}
): Promise<void> {
  console.log('\nCreating session using jam-ui form...');

  // Navigate to Create Session if not already there
  const currentUrl = page.url();
  if (!currentUrl.includes('session') || !currentUrl.includes('create')) {
    console.log('Navigating to Create Session page...');
    await navigateToSessionCreation(page);
  }

  // Fill and submit the session creation form
  await fillSessionForm(page, {
    sessionType: 'private',
    ...sessionData,
  });

  console.log('Session creation complete, should be in session interface now');
}

/**
 * Legacy function for compatibility - jam-ui uses form-based creation
 * @deprecated Use createAndJoinSession instead
 */
export async function clickQuickStart(page: Page, type: 'private' | 'public' | 'friends' = 'private'): Promise<void> {
  console.log('Note: jam-ui uses form-based session creation, not Quick Start buttons');
  await createAndJoinSession(page, { sessionType: type });
}

/**
 * Verify session interface is loaded
 */
export async function verifySessionInterfaceLoaded(page: Page): Promise<void> {
  // Check for key session interface elements
  const requiredElements = [
    { name: 'audio inputs', selectors: ['text=audio inputs', 'text=Audio Inputs', '[data-testid="audio-inputs"]'] },
    { name: 'personal mix', selectors: ['text=personal mix', 'text=Personal Mix', '[data-testid="personal-mix"]'] },
    { name: 'LEAVE button', selectors: ['text=LEAVE', 'button:has-text("LEAVE")', '[data-testid="leave-button"]'] },
  ];

  for (const element of requiredElements) {
    let found = false;
    for (const selector of element.selectors) {
      try {
        const el = await page.$(selector);
        if (el) {
          found = true;
          break;
        }
      } catch {
        continue;
      }
    }

    if (!found) {
      console.warn(`Expected element not found: ${element.name}`);
    }
  }
}

/**
 * Wait for API calls to settle
 */
export async function waitForAPICalls(page: Page, timeout: number = 3000): Promise<void> {
  await page.waitForLoadState('networkidle', { timeout }).catch(() => {});
  await page.waitForTimeout(1000);
}

/**
 * Dismiss any modals or overlays
 */
export async function dismissModals(page: Page): Promise<void> {
  // Try pressing Escape
  await page.keyboard.press('Escape');
  await page.waitForTimeout(500);

  // Try to remove dialog overlays
  await page.evaluate(() => {
    const overlays = document.querySelectorAll('.dialog-overlay, .modal-overlay, [role="dialog"]');
    overlays.forEach(overlay => {
      (overlay as HTMLElement).remove();
    });
  });

  await page.waitForTimeout(500);
}

/**
 * Extract session ID from current URL or page content
 */
export async function extractSessionId(page: Page): Promise<string | null> {
  // Try to extract from URL
  const url = page.url();
  const urlMatch = url.match(/session[s]?\/([a-f0-9-]{36})/i);
  if (urlMatch) {
    return urlMatch[1];
  }

  // Try to extract from page content
  const sessionId = await page.evaluate(() => {
    // Look for session ID in data attributes
    const sessionEl = document.querySelector('[data-session-id]');
    if (sessionEl) {
      return sessionEl.getAttribute('data-session-id');
    }

    // Look for session ID in window object
    if ((window as any).sessionId) {
      return (window as any).sessionId;
    }

    return null;
  });

  return sessionId;
}
