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

const testUser = {
  id: 'user-checkout-regression',
  name: 'Checkout Regression',
  displayName: 'Checkout Regression',
  phone: '13600000000',
  passportNo: 'P0001',
  email: 'checkout@example.com',
  organization: 'Regression Lab',
  onboardingCompleted: true,
  membershipLevel: 'registered',
}

const appUser = {
  id: testUser.id,
  name: testUser.displayName,
  phone: testUser.phone,
  passportNo: testUser.passportNo,
  email: testUser.email,
  organization: testUser.organization,
  onboardingCompleted: true,
  membershipLevel: 0,
}

type CapturedBodies = {
  previews: unknown[]
  orders: unknown[]
}

function orderResponse(productIds: string[], typeById: Record<string, string> = {}) {
  return {
    id: 'order-backend-id',
    orderNo: 'ORD-CHECKOUT-REAL-ID',
    settlementNo: 'CKO-CHECKOUT-REAL-ID',
    status: 'paid',
    createdAt: new Date().toISOString(),
    subtotalAmount: productIds.length * 10000,
    memberDiscountAmount: 0,
    couponDiscountAmount: 0,
    totalAmount: productIds.length * 10000,
    items: productIds.map((productId) => ({
      productId,
      productType: typeById[productId] || 'course',
      titleSnapshot: productId,
      unitPriceAmount: 10000,
      quantity: 1,
    })),
  }
}

function previewResponse(productIds: string[]) {
  return {
    subtotalAmount: productIds.length * 10000,
    memberDiscountAmount: 0,
    couponDiscountAmount: 0,
    totalAmount: productIds.length * 10000,
    items: productIds.map(() => ({
      unitPriceAmount: 10000,
      listPriceAmount: 10000,
      pricingSource: 'list_price',
    })),
  }
}

async function loginWithCart(page: Page, cartItems: unknown[] = [], orders: unknown[] = []) {
  await page.addInitScript(({ user, cart, savedOrders }) => {
    window.localStorage.setItem('dlbdi:token', JSON.stringify('checkout-test-token'))
    window.localStorage.setItem('dlbdi:user', JSON.stringify(user))
    window.localStorage.setItem('dlbdi:cart', JSON.stringify(cart))
    window.localStorage.setItem('dlbdi:orders', JSON.stringify(savedOrders))
  }, { user: appUser, cart: cartItems, savedOrders: orders })
}

async function mockCheckoutApi(page: Page, captured: CapturedBodies, options: { membershipCatalogFails?: boolean } = {}) {
  await page.route('**/api/**', async (route) => {
    const request = route.request()
    const url = new URL(request.url())
    const path = url.pathname.replace(/^\/api/, '')

    if (path === '/account/me') {
      await route.fulfill({ contentType: 'application/json', body: JSON.stringify(testUser) })
      return
    }
    if (path === '/account/orders' || path === '/account/tasks' || path === '/account/consulting-requests') {
      await route.fulfill({ contentType: 'application/json', body: JSON.stringify({ items: [] }) })
      return
    }
    if (path === '/site/agreements/purchase-terms') {
      await route.fulfill({ contentType: 'application/json', body: JSON.stringify({ id: 'purchase-terms', title: 'Terms', content: 'Terms' }) })
      return
    }
    if (path === '/membership/catalog') {
      if (options.membershipCatalogFails) {
        await route.fulfill({ status: 503, contentType: 'application/json', body: JSON.stringify({ message: 'catalog unavailable' }) })
        return
      }
      await route.fulfill({
        contentType: 'application/json',
        body: JSON.stringify({
          plans: [
            {
              productId: 'member-plan-real-senior-2026',
              slug: 'senior',
              level: 'senior',
              name: 'Senior Member',
              badge: 'Senior',
              description: 'Senior plan',
              ctaLabel: 'Buy',
              tone: 'gold',
              monthlyPriceAmount: 39900,
              yearlyPriceAmount: 399900,
              recommended: true,
              sortOrder: 1,
              status: 'published',
              groups: [{ id: 'core', title: 'Core', items: ['Dedicated service', 'Priority booking'] }],
            },
          ],
          compareRows: [],
          faqs: [],
        }),
      })
      return
    }
    if (path === '/checkout/preview' && request.method() === 'POST') {
      const body = request.postDataJSON()
      captured.previews.push(body)
      await route.fulfill({ contentType: 'application/json', body: JSON.stringify(previewResponse(body.items.map((item: { productId: string }) => item.productId))) })
      return
    }
    if (path === '/orders' && request.method() === 'POST') {
      const body = request.postDataJSON()
      captured.orders.push(body)
      const productIds = body.items.map((item: { productId: string }) => item.productId)
      const typeById = Object.fromEntries(body.items.map((item: { productId: string }, index: number) => [item.productId, index === 0 ? 'course' : index === 1 ? 'event' : index === 2 ? 'agent' : 'membership']))
      await route.fulfill({ contentType: 'application/json', body: JSON.stringify(orderResponse(productIds, typeById)) })
      return
    }

    await route.fulfill({ status: 404, contentType: 'application/json', body: JSON.stringify({ message: `Unhandled ${path}` }) })
  })
}

async function submitCheckout(page: Page) {
  await page.getByRole('button', { name: '下一步' }).click()
  await page.locator('input[type="checkbox"]').check()
  await page.getByRole('button', { name: /确认/ }).click()
}

test('cart checkout preview and order payloads keep real product ids', async ({ page }) => {
  const captured: CapturedBodies = { previews: [], orders: [] }
  await mockCheckoutApi(page, captured)
  await loginWithCart(page, [
    { id: 'course-real-city-ops-2026', type: 'course', title: 'Course', price: 100, href: '/courses/course' },
    { id: 'event-real-ai-salon-2026', type: 'event', title: 'Event', price: 100, href: '/events/event' },
    { id: 'agent-real-policy-copilot-2026', type: 'agent', title: 'Agent', price: 100, href: '/agents/agent' },
  ])

  await page.goto('/checkout')
  await expect.poll(() => captured.previews.length).toBeGreaterThan(0)
  await submitCheckout(page)
  await expect.poll(() => captured.orders.length).toBe(1)

  const previewIds = (captured.previews.at(-1) as { items: { productId: string }[] }).items.map((item) => item.productId)
  const orderIds = (captured.orders[0] as { items: { productId: string }[] }).items.map((item) => item.productId)
  expect(previewIds).toEqual(['course-real-city-ops-2026', 'event-real-ai-salon-2026', 'agent-real-policy-copilot-2026'])
  expect(orderIds).toEqual(previewIds)
  expect(orderIds).not.toContain('course-city-method')
  expect(orderIds).not.toContain('agent-policy-brief')
})

test('direct membership checkout uses catalog product id and blocks catalog failure', async ({ page }) => {
  const captured: CapturedBodies = { previews: [], orders: [] }
  await mockCheckoutApi(page, captured)
  await loginWithCart(page)

  await page.goto('/checkout?type=membership&plan=senior&cycle=yearly')
  await expect.poll(() => captured.previews.length).toBeGreaterThan(0)
  await submitCheckout(page)
  await expect.poll(() => captured.orders.length).toBe(1)

  expect((captured.previews.at(-1) as { items: { productId: string }[] }).items[0].productId).toBe('member-plan-real-senior-2026')
  expect((captured.orders[0] as { items: { productId: string }[] }).items[0].productId).toBe('member-plan-real-senior-2026')
})

test('direct membership checkout does not fall back when catalog fails', async ({ page }) => {
  const captured: CapturedBodies = { previews: [], orders: [] }
  await mockCheckoutApi(page, captured, { membershipCatalogFails: true })
  await loginWithCart(page)

  await page.goto('/checkout?type=membership&plan=senior&cycle=yearly')
  await expect(page.locator('body')).toContainText('catalog unavailable')
  await expect(page.locator('aside button')).toBeDisabled()

  expect(captured.previews).toEqual([])
  expect(captured.orders).toEqual([])
})

test('membership success primary action opens account membership page', async ({ page }) => {
  await loginWithCart(page, [], [{
    id: 'ORD-MEMBER-SUCCESS',
    createdAt: new Date().toISOString(),
    items: [{ id: 'member-plan-real-senior-2026', type: 'membership', title: 'Senior Member', price: 3999, href: '/membership', quantity: 1 }],
    subtotal: 3999,
    discount: 0,
    total: 3999,
    paymentMethod: 'wechat',
    status: '已支付',
  }])

  await page.goto('/checkout/success?orderId=ORD-MEMBER-SUCCESS')
  await expect(page.getByRole('link', { name: /查看会员权益/ })).toHaveAttribute('href', '/account/membership')
})

test('account order detail service action uses backend service entry href', async ({ page }) => {
  await page.route('**/api/**', async (route) => {
    const request = route.request()
    const url = new URL(request.url())
    const path = url.pathname.replace(/^\/api/, '')

    if (path === '/account/me') {
      await route.fulfill({ contentType: 'application/json', body: JSON.stringify(testUser) })
      return
    }
    if (path === '/account/orders/ORD-SERVICE-HREF') {
      await route.fulfill({
        contentType: 'application/json',
        body: JSON.stringify({
          id: 'order-service-href-id',
          orderNo: 'ORD-SERVICE-HREF',
          settlementNo: 'CKO-SERVICE-HREF',
          userId: testUser.id,
          status: 'paid',
          subtotalAmount: 10000,
          memberDiscountAmount: 0,
          couponDiscountAmount: 0,
          paidAmount: 10000,
          totalAmount: 10000,
          currency: 'CNY',
          createdAt: new Date().toISOString(),
          updatedAt: new Date().toISOString(),
          items: [{
            productId: 'course-real-city-ops-2026',
            productType: 'course',
            titleSnapshot: 'Course',
            unitPriceAmount: 10000,
            quantity: 1,
            payableAmount: 10000,
            serviceEntryType: 'course',
            serviceEntryId: 'registration-real-001',
            serviceEntryHref: '/account/courses/registration-real-001',
          }],
        }),
      })
      return
    }
    if (path === '/account/orders' || path === '/account/tasks' || path === '/account/consulting-requests') {
      await route.fulfill({ contentType: 'application/json', body: JSON.stringify({ items: [] }) })
      return
    }

    await route.fulfill({ status: 404, contentType: 'application/json', body: JSON.stringify({ message: `Unhandled ${path}` }) })
  })
  await loginWithCart(page)

  await page.goto('/account/orders/ORD-SERVICE-HREF')

  await expect(page.getByRole('link', { name: /继续学习/ })).toHaveAttribute('href', '/account/courses/registration-real-001')
})
