import { expect, test } from '@playwright/test'
import { execFileSync } from 'node:child_process'

const apiBase = (process.env.API_BASE || 'http://localhost:4000/api').replace(/\/+$/, '')
const adminToken = process.env.ADMIN_TOKEN || 'dev-admin-token'
const runId = process.env.RUN_ID || `REGRESSION-WEB-${new Date().toISOString().replace(/[-:.TZ]/g, '').slice(0, 14)}-${process.pid}`
const runIpSegment = (Date.now() % 200) + 20

function uniquePhone(offset = 0) {
  const seed = (Date.now() + offset) % 100000000
  return `136${String(seed).padStart(8, '0')}`
}

function testClientIp(offset = 0) {
  return `10.72.${runIpSegment}.${(offset % 200) + 20}`
}

async function api(path: string, options: RequestInit = {}, clientIp = testClientIp()) {
  const response = await fetch(`${apiBase}${path}`, {
    ...options,
    headers: {
      'content-type': 'application/json',
      'x-forwarded-for': clientIp,
      ...(options.headers || {}),
    },
  })
  const text = await response.text()
  const data = text ? JSON.parse(text) : null
  if (!response.ok) throw new Error(data?.message || `${path} failed with ${response.status}`)
  return data
}

function latestLocalPhoneCode(phone: string) {
  const database = process.env.PGDATABASE || process.env.DATABASE_NAME || 'dlbdi_dev'
  try {
    return execFileSync('psql', [
      '-At',
      '-d',
      database,
      '-c',
      `select code from phone_codes where phone = '${phone}' and expires_at > now() order by created_at desc limit 1;`,
    ], {
      encoding: 'utf8',
      stdio: ['ignore', 'pipe', 'ignore'],
    }).trim()
  } catch {
    return ''
  }
}

async function createUserToken() {
  const phone = uniquePhone(30)
  const clientIp = testClientIp(30)
  await api('/admin/users', {
    method: 'POST',
    headers: { 'x-admin-token': adminToken },
    body: JSON.stringify({
      phone,
      displayName: `${runId}-ACCOUNT`,
      onboardingCompleted: true,
      status: 'active',
    }),
  })
  const sent = await api('/auth/phone/send-code', {
    method: 'POST',
    body: JSON.stringify({ phone }),
  }, clientIp)
  const login = await api('/auth/phone/login', {
    method: 'POST',
    body: JSON.stringify({ phone, code: sent.demoCode || latestLocalPhoneCode(phone) || process.env.DEV_AUTH_CODE || '123456' }),
  }, clientIp)
  const token = login.token as string
  const user = await api('/account/me', {
    headers: { authorization: `Bearer ${token}` },
  }, clientIp)
  return { token, user }
}

function membershipLevelValue(level: string) {
  if (level === 'senior') return 2
  if (level === 'junior') return 1
  return 0
}

async function loginAccount(page: import('@playwright/test').Page, session: { token: string; user: Record<string, string | boolean | null | undefined> }) {
  const profile = {
    id: session.user.id,
    name: session.user.displayName || session.user.phone || '研究院用户',
    phone: session.user.phone,
    passportNo: session.user.passportNo,
    wechatId: session.user.wechatId,
    contactPhone: session.user.contactPhone,
    email: session.user.email,
    organization: session.user.organization,
    title: session.user.title,
    city: session.user.city,
    address: session.user.address,
    industry: session.user.industry,
    invoiceTitle: session.user.invoiceTitle,
    taxNumber: session.user.taxNumber,
    invoiceEmail: session.user.invoiceEmail,
    authProvider: session.user.wechatId && !session.user.phone ? 'wechat' : 'phone',
    onboardingCompleted: session.user.onboardingCompleted,
    expertApplicationStatus: session.user.expertApplicationStatus,
    expertProfileStatus: session.user.expertProfileStatus,
    membershipLevel: membershipLevelValue(String(session.user.membershipLevel || 'registered')),
  }
  await page.addInitScript((value) => {
    window.localStorage.setItem('dlbdi:token', JSON.stringify(value.token))
    window.localStorage.setItem('dlbdi:user', JSON.stringify(value.profile))
  }, { token: session.token, profile })
}

test('public SSR pages render without internal API URL failures', async ({ request }) => {
  test.setTimeout(60_000)
  const pages = [
    { path: '/', content: /近期课程|近期活动|关于研究院/ },
    { path: '/about', content: /关于我们|关于研究院/ },
    { path: '/consulting', content: /规划咨询/ },
    { path: '/data', content: /数据服务/ },
    { path: '/agents', content: /智能体|AI/ },
    { path: '/courses', content: /课程目录|暂无课程|推荐课程/ },
    { path: '/events', content: /活动|报名/ },
    { path: '/experts', content: /专家平台/ },
    { path: '/news', content: /新闻资讯|暂无已发布资讯|资讯/ },
  ]
  for (const { path, content } of pages) {
    const response = await request.get(path)
    expect(response.status(), `${path} should render successfully`).toBe(200)
    const body = await response.text()
    expect(body, `${path} should include page-specific content`).toMatch(content)
    expect(body).not.toContain('ERR_INVALID_URL')
    expect(body).not.toContain('Failed to parse URL')
  }
})

test('account pages use backend-backed session and refreshable deep links', async ({ page }) => {
  test.setTimeout(60_000)
  const session = await createUserToken()
  const { token } = session
  await loginAccount(page, session)

  const catalog = await api('/membership/catalog')
  const plan = (catalog.plans || [])[0]
  expect(plan?.productId).toBeTruthy()
  const order = await api('/orders', {
    method: 'POST',
    headers: { authorization: `Bearer ${token}` },
    body: JSON.stringify({ items: [{ productId: plan.productId, quantity: 1, billingCycle: 'monthly' }] }),
  })
  expect(order.items?.[0]?.productId).toBe(plan.productId)

  await page.goto('/account/membership')
  await expect(page.getByText('会员状态', { exact: true })).toBeVisible({ timeout: 20_000 })
  await expect(page.locator('body')).not.toContainText('会员状态加载失败')

  await page.goto('/account/orders')
  await expect(page.locator('body')).toContainText(order.orderNo)

  await page.goto(`/account/orders/${encodeURIComponent(order.orderNo)}`)
  await expect(page.locator('body')).toContainText(order.orderNo)
  await page.reload()
  await expect(page.locator('body')).toContainText(order.orderNo, { timeout: 15000 })

  for (const path of ['/account/data', '/account/consulting', '/account/courses', '/account/events', '/account/agents', '/account/expert-bookings']) {
    await page.goto(path, { waitUntil: 'domcontentloaded' })
    await expect(page.locator('body')).not.toContainText('Application error')
  }
})
