import { test as base, type APIRequestContext } from '@playwright/test';

/** Shape returned by POST /auth/register and POST /auth/login */
export interface TokenPair {
  accessToken: string;
  refreshToken: string;
}

let _counter = 0;

/** Generates a unique test user payload for each test run. */
export function createTestUser(suffix = `${Date.now()}${(++_counter).toString().padStart(4, '0')}${Math.random().toString(36).slice(2, 6)}`) {
  // Use last 8 digits of the combined suffix for the phone number
  const phoneSuffix = suffix.replace(/\D/g, '').slice(-8).padStart(8, '0');
  return {
    phone: `09${phoneSuffix}`,
    password: 'Test@1234!',
    fullName: `Test User ${suffix}`,
    email: `testuser${suffix}@goodgo.test`,
  };
}

/** Registers a new user via the API and returns the token pair. */
export async function registerUser(
  request: APIRequestContext,
  user = createTestUser(),
): Promise<TokenPair & { user: ReturnType<typeof createTestUser> }> {
  const res = await request.post('auth/register', { data: user });
  if (!res.ok()) {
    const body = await res.text();
    throw new Error(`Register failed (${res.status()}): ${body}`);
  }
  const tokens: TokenPair = await res.json();
  return { ...tokens, user };
}

/** Logs in an existing user and returns the token pair. */
export async function loginUser(
  request: APIRequestContext,
  phone: string,
  password: string,
): Promise<TokenPair> {
  const res = await request.post('auth/login', {
    data: { phone, password },
  });
  if (!res.ok()) {
    const body = await res.text();
    throw new Error(`Login failed (${res.status()}): ${body}`);
  }
  return res.json();
}

/**
 * Extended test fixture that provides a pre-authenticated API context.
 *
 * Usage:
 *   import { test } from '../fixtures/auth.fixture';
 *   test('my test', async ({ authedRequest, testTokens }) => { ... });
 */
export const test = base.extend<{
  testUser: ReturnType<typeof createTestUser>;
  testTokens: TokenPair;
  authedRequest: APIRequestContext;
}>({
  // eslint-disable-next-line no-empty-pattern
  testUser: async ({}, use) => {
    await use(createTestUser());
  },

  testTokens: async ({ request, testUser }, use) => {
    const { accessToken, refreshToken } = await registerUser(request, testUser);
    await use({ accessToken, refreshToken });
  },

  authedRequest: async ({ playwright, testTokens, baseURL }, use) => {
    const ctx = await playwright.request.newContext({
      baseURL,
      extraHTTPHeaders: {
        Authorization: `Bearer ${testTokens.accessToken}`,
      },
    });
    await use(ctx);
    await ctx.dispose();
  },
});

export { expect } from '@playwright/test';
