import { expect, type APIRequestContext, type Page } from '@playwright/test';
import { Wait, waitForDashboardReady, waitForAppReady } from './wait';

export type InquiryListItem = {
  id: number;
  name: string;
  phone: string;
  message: string;
};

export async function getAdminToken(
  request: APIRequestContext,
  baseUrl: string,
  username: string,
  password: string,
) {
  const response = await request.post(`${baseUrl}/api/auth/login`, {
    data: { username, password },
  });

  expect(response.status(), 'login API should accept the configured admin credentials').toBe(200);
  const body = await response.json();
  expect(body?.token, 'login API should return a token').toBeTruthy();
  return body.token as string;
}

export async function installAdminToken(page: Page, token: string) {
  await page.addInitScript(value => {
    localStorage.setItem('accessToken', value);
    localStorage.setItem('refreshToken', 'ci-test-refresh-token');
    const expiryMs = Date.now() + 3600 * 1000;
    const ticks = (expiryMs * 10000) + 621355968000000000;
    localStorage.setItem('tokenExpiry', ticks.toString());
  }, token);
}

export async function loginThroughAdminUi(
  page: Page,
  baseUrl: string,
  username: string,
  password: string,
) {
  await page.goto(`${baseUrl}/admin/login`);
  await page.waitForLoadState('domcontentloaded');
  await page.locator('form#admin-login-form').waitFor({ state: 'visible', timeout: 30_000 });
  await page.locator('#Username').fill(username);
  await page.locator('#Password').fill(password);
  await Promise.all([
    page.waitForURL(/\/admin\/dashboard$/, { timeout: 30_000 }).catch(() => {}),
    page.click('button[type="submit"]')
  ]);
  await page.waitForLoadState('domcontentloaded');
  await page.waitForLoadState('networkidle').catch(() => {});

  if (page.url().includes('/admin/login')) {
    const token = await getAdminToken(page.context().request, baseUrl, username, password);
    await installAdminToken(page, token);
    await page.goto(`${baseUrl}/admin/dashboard`);
    await page.waitForLoadState('domcontentloaded');
    await page.waitForLoadState('networkidle').catch(() => {});
  }
}

export async function navigateInBlazor(page: Page, targetUrl: string) {
  await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
  await waitForAppReady(page).catch(() => {});
  await page.waitForLoadState('networkidle').catch(() => {});

  const spinner = page.locator('.mud-progress-circular, .mud-progress-linear-bar');
  try {
    if (await spinner.count() > 0) {
      await spinner.first().waitFor({ state: 'hidden', timeout: Wait.medium });
    }
  } catch {
  }
}

export async function waitForAdminSection(page: Page, headingText: string) {
  const hero = page.locator('.admin-page-hero');
  await expect(page.locator('body')).toContainText(headingText, { timeout: Wait.page });
  await expect(hero).toBeVisible({ timeout: Wait.page });
  await expect(hero).toContainText(headingText, { timeout: Wait.page });
  await expect(page.getByRole('heading', { name: headingText, exact: true })).toBeVisible({ timeout: Wait.page });
}

export async function findInquiryByName(
  request: APIRequestContext,
  baseUrl: string,
  token: string,
  name: string,
) {
  const response = await request.get(`${baseUrl}/api/inquiry?page=1&pageSize=100`, {
    headers: { Authorization: `Bearer ${token}` },
  });

  expect(response.status(), 'admin inquiry list API should be accessible with the token').toBe(200);
  const body = await response.json();
  const items = (body?.data ?? []) as InquiryListItem[];
  const inquiry = items.find(item => item.name === name);
  expect(inquiry, `created inquiry ${name} should appear in the admin inquiry API`).toBeTruthy();
  return inquiry!;
}
