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

type MockOptions = {
  sessionStatus?: number;
  captureApprove?: (pendingRef: string | null) => void;
};

async function seedTokenLogin(page: Page): Promise<void> {
  await page.addInitScript(() => {
    window.localStorage.setItem('baron_auth_token', 'e30.e30.e30');
    window.localStorage.setItem('baron_auth_provider', 'ory');
    window.localStorage.removeItem('baron_auth_cookie_mode');
    window.localStorage.removeItem('baron_auth_pending_provider');
  });
}

async function seedSessionTokenLogin(page: Page): Promise<void> {
  await page.addInitScript(() => {
    window.sessionStorage.setItem('baron_auth_token', 'e30.e30.e30');
    window.sessionStorage.setItem('baron_auth_provider', 'ory');
    window.sessionStorage.removeItem('baron_auth_cookie_mode');
    window.sessionStorage.removeItem('baron_auth_pending_provider');
    window.localStorage.removeItem('baron_auth_token');
    window.localStorage.removeItem('baron_auth_provider');
    window.localStorage.removeItem('baron_auth_cookie_mode');
    window.localStorage.removeItem('baron_auth_pending_provider');
  });
}

async function mockUserfrontApis(
  page: Page,
  options: MockOptions = {},
): Promise<void> {
  const sessionStatus = options.sessionStatus ?? 200;

  await page.route('**/api/v1/**', async (route: Route) => {
    const requestUrl = new URL(route.request().url());
    const path = requestUrl.pathname;

    if (path.endsWith('/api/v1/user/me')) {
      if (sessionStatus === 200) {
        await route.fulfill({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({
            id: 'e2e-user',
            email: 'e2e@example.com',
            name: 'E2E User',
            phone: '+821012341234',
            department: 'QA',
            affiliationType: 'employee',
            companyCode: 'BARON',
            tenant: {
              id: 'tenant-1',
              name: 'Baron',
              slug: 'baron',
              description: 'E2E tenant',
            },
          }),
        });
        return;
      }

      await route.fulfill({
        status: sessionStatus,
        contentType: 'application/json',
        body: JSON.stringify({ error: 'unauthorized' }),
      });
      return;
    }

    if (path.endsWith('/api/v1/user/rp/linked')) {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ items: [] }),
      });
      return;
    }

    if (path.endsWith('/api/v1/audit/auth/timeline')) {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ items: [], next_cursor: '' }),
      });
      return;
    }

    if (path.endsWith('/api/v1/auth/qr/approve')) {
      if (route.request().method() == 'POST') {
        let pendingRef: string | null = null;
        try {
          const body = (route.request().postDataJSON() ?? {}) as {
            pendingRef?: string;
          };
          pendingRef = body.pendingRef ?? null;
          console.log(`[E2E-MOCK] /api/v1/auth/qr/approve POST body:`, body);
        } catch (e) {
          console.log(`[E2E-MOCK] /api/v1/auth/qr/approve POST body parse error:`, e);
          pendingRef = null;
        }
        options.captureApprove?.(pendingRef);
      } else {
        console.log(`[E2E-MOCK] /api/v1/auth/qr/approve ${route.request().method()} request`);
      }
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ ok: true }),
      });
      return;
    }

    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({}),
    });
  });
}

test.describe('UserFront WASM auth routing', () => {
  test('비로그인 /ko 진입 시 /ko/signin 으로 리다이렉트된다', async ({ page }) => {
    await mockUserfrontApis(page, { sessionStatus: 401 });

    await page.goto('/ko');

    await expect(page).toHaveURL(/\/ko\/signin(?:\?.*)?$/);
  });

  test('로그인 상태 /ko 진입 후 새로고침해도 /ko/dashboard 를 유지한다', async ({
    page,
  }) => {
    await seedTokenLogin(page);
    await mockUserfrontApis(page);

    await page.goto('/ko');
    await expect(page).toHaveURL(/\/ko\/dashboard$/);

    await page.reload();
    await expect(page).toHaveURL(/\/ko\/dashboard$/);
  });

  test('sessionStorage 기반 로그인 상태에서도 /ko/dashboard 를 유지한다', async ({
    page,
  }) => {
    await seedSessionTokenLogin(page);
    await mockUserfrontApis(page);

    await page.goto('/ko');
    await expect(page).toHaveURL(/\/ko\/dashboard$/);
  });

  test('비로그인 /ko/approve 는 signin(+notice)으로 이동한다', async ({ page }) => {
    await mockUserfrontApis(page, { sessionStatus: 401 });

    await page.goto('/ko/approve?ref=e2e-ref');

    await expect(page).toHaveURL(/\/ko\/signin\?notice=qr_login_required$/);
  });

  test('로그인 상태 /ko/approve 는 승인 API 호출 후 dashboard로 이동한다', async ({
    page,
  }) => {
    let approvedRef: string | null = null;

    await seedTokenLogin(page);
    await mockUserfrontApis(page, {
      captureApprove: (pendingRef) => {
        approvedRef = pendingRef;
      },
    });

    await page.goto('/ko/approve?ref=e2e-approve-ref');

    await expect(page).toHaveURL(/\/ko\/dashboard(?:\?.*)?$/, {
      timeout: 10_000,
    });
    expect(approvedRef).toBe('e2e-approve-ref');
  });
});
