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

const USERFRONT_BASE_URL = process.env.USERFRONT_BASE_URL ?? 'https://sso-test.hmac.kr';
const ADMINFRONT_URL = process.env.ADMINFRONT_URL ?? 'http://localhost:5173';
const LOGIN_ID = process.env.E2E_LOGIN_ID ?? '';
const PASSWORD = process.env.E2E_PASSWORD ?? '';

type SessionApiResponse = {
  items?: Array<{
    session_id?: string;
    client_id?: string;
    app_name?: string;
    is_current?: boolean;
    user_agent?: string;
    ip_address?: string;
  }>;
};

function ensureCredentials(): void {
  if (!LOGIN_ID || !PASSWORD) {
    test.skip(true, 'E2E credentials are required');
  }
}

async function enableFlutterAccessibility(page: Page): Promise<void> {
  await page.waitForTimeout(300);
  const button = page.getByRole('button', { name: 'Enable accessibility' });
  if (await button.count()) {
    try {
      await button.click({ force: true });
    } catch {
      return;
    }
    const placeholder = page.locator('flt-semantics-placeholder');
    if (await placeholder.count()) {
      await placeholder.first().click({ force: true });
    }
    await page.waitForTimeout(800);
  }
}

async function clickPasswordTab(page: Page): Promise<void> {
  await page.waitForTimeout(900);
  const pane = page.locator('flt-glass-pane');
  await pane.click({
    position: { x: 522, y: 158 },
    force: true,
  });
  await page.waitForTimeout(120);
  await pane.click({
    position: { x: 522, y: 158 },
    force: true,
  });
  await page.waitForTimeout(200);
}

async function fillAt(page: Page, x: number, y: number, value: string): Promise<void> {
  const pane = page.locator('flt-glass-pane');
  await pane.click({ position: { x, y }, force: true });
  await page.waitForTimeout(100);
  await page.keyboard.press('Control+A');
  await page.keyboard.press('Backspace');
  await page.keyboard.type(value);
}

async function loginViaUserFront(page: Page): Promise<void> {
  await page.waitForURL(/\/ko\/(signin|login)/, { timeout: 30_000 });
  const loginIdInput = page.getByPlaceholder(/이메일 또는 휴대폰 번호|email|phone/i);
  const passwordInput = page.getByPlaceholder(/비밀번호|password/i);
  const submitButton = page.getByRole('button', { name: /로그인|Login/i });

  if ((await loginIdInput.count()) >= 1 && (await passwordInput.count()) >= 1) {
    await loginIdInput.first().fill(LOGIN_ID);
    await passwordInput.first().fill(PASSWORD);
    await submitButton.click();
    return;
  }

  await clickPasswordTab(page);
  await fillAt(page, 640, 245, LOGIN_ID);
  await fillAt(page, 640, 311, PASSWORD);
  await page.locator('flt-glass-pane').click({
    position: { x: 640, y: 381 },
    force: true,
  });
}

async function ensureConsentIfNeeded(page: Page): Promise<void> {
  if (!/\/ko\/consent/.test(page.url())) {
    return;
  }

  const allowButton = page
    .getByRole('button')
    .filter({ hasText: /허용|동의|Accept|Allow/i })
    .first();

  if (await allowButton.count()) {
    await allowButton.click({ force: true });
  }
}

async function captureUserSessionsOnReload(page: Page): Promise<SessionApiResponse> {
  const responsePromise = page.waitForResponse(
    (response) =>
      response.request().method() === 'GET' &&
      response.url().includes('/api/v1/user/sessions'),
    { timeout: 30_000 },
  );

  await page.reload({ waitUntil: 'domcontentloaded' });
  const response = await responsePromise;
  return (await response.json()) as SessionApiResponse;
}

async function loginUserFront(context: BrowserContext): Promise<Page> {
  const page = await context.newPage();
  await page.goto(`${USERFRONT_BASE_URL}/ko/signin`, {
    waitUntil: 'domcontentloaded',
  });
  await loginViaUserFront(page);
  await expect(page).toHaveURL(/\/ko\/dashboard/, { timeout: 60_000 });
  return page;
}

async function loginAdminFront(context: BrowserContext): Promise<Page> {
  const page = await context.newPage();
  await page.goto(ADMINFRONT_URL, { waitUntil: 'domcontentloaded' });
  const ssoButton = page.getByRole('button', { name: /SSO 계정으로 로그인|SSO/i });
  if (await ssoButton.count()) {
    await ssoButton.click({ force: true });
    await page.waitForTimeout(1500);
  }
  if (/\/login$/.test(page.url())) {
    const authorizeUrl = await page.evaluate(() => {
      const origin = window.location.origin;
      const authority = 'https://sso-test.hmac.kr/oidc';
      const params = new URLSearchParams({
        client_id: 'adminfront',
        redirect_uri: `${origin}/auth/callback`,
        response_type: 'code',
        scope: 'openid offline_access profile email',
        state: `pw-${Date.now()}`,
        nonce: `pw-${Date.now()}`,
        code_challenge: 'test-code-challenge-test-code-challenge-test',
        code_challenge_method: 'plain',
      });
      return `${authority}/oauth2/auth?${params.toString()}`;
    });
    await page.goto(authorizeUrl, { waitUntil: 'domcontentloaded' });
  }
  await loginViaUserFront(page);
  await ensureConsentIfNeeded(page);
  await page.waitForURL(/localhost:5173|\/auth\/callback|\/dashboard|\/tenants/, {
    timeout: 60_000,
  });
  return page;
}

test.describe('cross-browser session debug', () => {
  test('userfront session card should map adminfront session metadata across contexts', async ({
    browser,
  }, testInfo) => {
    ensureCredentials();

    const userfrontContext = await browser.newContext({ locale: 'ko-KR' });
    const adminfrontContext = await browser.newContext({ locale: 'ko-KR' });

    const userfrontPage = await loginUserFront(userfrontContext);
    const adminfrontPage = await loginAdminFront(adminfrontContext);

    const sessionsPayload = await captureUserSessionsOnReload(userfrontPage);
    const items = sessionsPayload.items ?? [];
    const adminfrontItems = items.filter((item) =>
      (item.client_id ?? '').toLowerCase().includes('adminfront'),
    );
    const unknownCards = await userfrontPage.locator('text=세션 정보').allTextContents();
    const adminFrontCards = await userfrontPage.locator('text=AdminFront').allTextContents();

    await testInfo.attach('user-sessions.json', {
      body: JSON.stringify(sessionsPayload, null, 2),
      contentType: 'application/json',
    });
    await testInfo.attach('card-summary.json', {
      body: JSON.stringify(
        {
          unknownCards,
          adminFrontCards,
          currentUrl: userfrontPage.url(),
          adminfrontUrl: adminfrontPage.url(),
        },
        null,
        2,
      ),
      contentType: 'application/json',
    });

    expect(adminfrontItems.length).toBeGreaterThan(0);
  });
});
