import { Given, When, Then, expect } from '../fixtures/bdd-fixtures';
import { AuthUtils } from '../utils/authUtils';

// ===== Background / Setup Steps =====

Given('the Fellowship SUT is running', async ({ page }) => {
  try {
    const baseUrl = global.fixtures.baseUrl;
    const response = await page.request.get(`${baseUrl}/health`);
    if (!response.ok()) {
      throw new Error(`SUT not running: ${response.status()}`);
    }
  } catch (e) {
    console.warn('SUT health check failed, proceeding with test');
  }
});


Given('I am logged in as {string}', async ({ page }, username: string) => {
  await global.fixtures.loginPage!.goto();
  const user = AuthUtils.getFellowshipMember(username);
  await global.fixtures.loginPage!.loginWithUser(user);
  await global.fixtures.loginPage!.waitForDashboard();
  expect(page.url()).toContain('/dashboard');
});

Given('I navigate to the {string}', async ({ page }, pageName: string) => {
  const pageMapping: Record<string, any> = {
    'login page': global.fixtures.loginPage,
    'dashboard': global.fixtures.dashboardPage,
    'quests page': global.fixtures.questsPage,
    'map': global.fixtures.mapPage,
  };
  const targetPage = pageMapping[pageName.toLowerCase()];
  if (!targetPage) throw new Error(`Unknown page: ${pageName}`);
  await targetPage.goto();
});

Given('I start with {int} gold', async ({ page }, goldAmount: number) => {
  global.fixtures.testContext!.goldAmount = goldAmount;
});

// ===== Authentication Steps =====

When('I log in with username {string} and password {string}', async ({ page }, username: string, password: string) => {
  try {
    const user = AuthUtils.getFellowshipMember(username);
    await global.fixtures.loginPage!.loginWithUser(user);
  } catch {
    await global.fixtures.loginPage!.login(username, password);
  }
  // Wait for URL to change to dashboard (success) or error to appear (failure)
  await Promise.race([
    page.waitForURL('**/dashboard', { timeout: 12000 }),
    page.waitForSelector('h4', { timeout: 12000 }),
  ]).catch(() => {
    // Let next step handle evaluation
  });
});

When('I navigate to the signup page', async () => {
  await global.fixtures.loginPage!.goToSignup();
});

When('I sign up with username {string} and password {string}', async ({ page }, username: string, password: string) => {
  const uniqueUsername = `${username}_${Date.now()}`;
  await global.fixtures.loginPage!.signup(uniqueUsername, password);
  await Promise.race([
    page.waitForURL('**/dashboard', { timeout: 15000 }),
    page.waitForSelector('h4', { timeout: 15000 }),
  ]).catch(() => {});
});

When('I am on the dashboard', async () => {
  const isLoaded = await global.fixtures.dashboardPage!.isLoaded();
  expect(isLoaded).toBeTruthy();
});

When('I refresh the page', async ({ page }) => {
  await page.reload();
});

When('I click the logout button', async () => {
  await global.fixtures.dashboardPage!.logout();
});

When('I try to create a quest without being logged in', async ({ context, page }) => {
  const baseUrl = global.fixtures.baseUrl;
  const response = await context.request.post(`${baseUrl}/api/quests`, {
    data: { title: 'Test' },
  });
  (global.fixtures.testContext as any).lastErrorStatus = response.status();
});

When('I verify CORS preflight for the login endpoint', async ({ context, page }) => {
  const baseUrl = global.fixtures.baseUrl;
  (global.fixtures.testContext as any).corsAllowed = await global.fixtures.fixtureUtils.verifyCORSPreflight(
    context.request,
    baseUrl,
    'http://localhost:3000'
  );
});

// ===== Assertion Steps =====

Then('I should be redirected to the dashboard', async ({ page }) => {
  await page.waitForURL('**/dashboard', { timeout: 15000 });
  expect(page.url()).toContain('/dashboard');
});

Then('the dashboard should display a personalized greeting for {string}', async ({ page }, characterName: string) => {
  await global.fixtures.dashboardPage!.expectGreetingForCharacter(characterName);
});

Then('I should see an error message containing {string}', async ({ page }, expectedText: string) => {
  const isError = await global.fixtures.loginPage!.isErrorVisible();
  expect(isError).toBeTruthy();
  const errorText = await global.fixtures.loginPage!.getErrorText();
  expect(errorText.toLowerCase()).toContain(expectedText.toLowerCase());
});

Then('I should be logged in as {string}', async ({ page }, _username: string) => {
  await page.waitForURL('**/dashboard', { timeout: 15000 }).catch(() => {});
  expect(page.url()).toContain('/dashboard');
});

Then('I should land on the dashboard', async ({ page }) => {
  await page.waitForURL('**/dashboard', { timeout: 15000 }).catch(() => {});
  expect(page.url()).toContain('/dashboard');
});

Then('I should still be logged in', async ({ page }) => {
  await page.waitForURL('**/dashboard', { timeout: 10000 }).catch(() => {});
  expect(page.url()).toContain('/dashboard');
});

Then('the dashboard should be loaded', async () => {
  const isLoaded = await global.fixtures.dashboardPage!.isLoaded();
  expect(isLoaded).toBeTruthy();
});

Then('I should be redirected to the login page', async ({ page }) => {
  await page.waitForURL('**/login', { timeout: 15000 });
  expect(page.url()).toContain('/login');
});

Then('the session should be cleared', async ({ page }) => {
  await page.waitForURL('**/login', { timeout: 10000 }).catch(() => {});
  expect(page.url()).toContain('/login');
});

Then('I should receive an unauthorized error', async () => {
  expect((global.fixtures.testContext as any).lastErrorStatus).toBe(401);
});

Then('the response should allow POST requests', async () => {
  expect((global.fixtures.testContext as any).corsAllowed).toBeTruthy();
});

Then('the response should include proper CORS headers', async () => {
  expect((global.fixtures.testContext as any).corsAllowed).toBeTruthy();
});
