/**
 * Sprint 8 пункт 1 — SignalR smoke на стейдже.
 * Открываем /dashboard, проверяем что live-индикатор стал "live",
 * затем через API проводим продажу, ждём что виджет «Выручка сегодня»
 * увеличился без перезагрузки страницы.
 */
import { test, expect, request as apiRequest } from '@playwright/test'
import { apiSignup, attachSession, watchPage } from '../lib/ui.js'

const BASE = process.env.E2E_ADMIN_URL ?? 'https://test.admin.food-market.kz'

test.describe('SignalR realtime', () => {
  test('S8-1 dashboard live-индикатор + SalePosted увеличивает счётчик чеков', async ({ page }) => {
    test.setTimeout(120_000)
    const sess = await apiSignup('s8sr')
    const errs = watchPage(page)

    // Сначала засеем демо-данные чтобы был товар + остаток.
    const ctx = await apiRequest.newContext({
      baseURL: BASE, ignoreHTTPSErrors: true,
      extraHTTPHeaders: { Authorization: `Bearer ${sess.accessToken}` },
    })
    await ctx.post('/api/admin/seed-demo', { data: {} })

    await attachSession(page, sess, '/dashboard')
    await page.waitForLoadState('networkidle')

    // live-индикатор появляется когда SignalR подсоединился (5с буфер)
    await expect(page.getByText('live').first()).toBeVisible({ timeout: 15_000 })

    // Считаем текущее число чеков (виджет «Выручка сегодня» / hint)
    const initialHint = await page.locator('text=/\\d+\\s+чеков/').first().textContent()
    const initial = initialHint ? parseInt(initialHint, 10) : 0

    // Через API создаём чек и проводим. После этого UI должен увеличиться.
    type Paged<T> = { items: T[] }
    const stores = await (await ctx.get('/api/catalog/stores')).json() as Paged<{ id: string; isMain: boolean }>
    const retailPoints = await (await ctx.get('/api/catalog/retail-points')).json() as Paged<{ id: string }>
    const curs = await (await ctx.get('/api/catalog/currencies')).json() as Paged<{ id: string; code: string }>
    const storeId = stores.items.find(s => s.isMain)!.id
    const retailPointId = retailPoints.items[0]?.id
    const kztId = curs.items.find(c => c.code === 'KZT')!.id

    // Чтобы не зависеть от того что seed-demo не выкупил весь товар, ищем
    // продукт с положительным stock на main-складе.
    const stocks = await (await ctx.get(`/api/inventory/stock?storeId=${storeId}&pageSize=50`)).json() as Paged<{ productId: string; quantity: number }>
    const withStock = stocks.items.find(s => s.quantity > 1)
    expect(withStock, 'нужен хотя бы один продукт с остатком >1').toBeTruthy()
    const products = await (await ctx.get(`/api/catalog/products?pageSize=100`)).json() as Paged<{ id: string; prices: { amount: number }[] }>
    const prod = products.items.find(p => p.id === withStock!.productId)!
    const price = prod.prices[0]?.amount ?? 100

    const saleResp = await ctx.post('/api/sales/retail', {
      data: {
        date: new Date().toISOString(),
        storeId, retailPointId, currencyId: kztId,
        payment: 0, isReturn: false,
        lines: [{ productId: prod.id, quantity: 1, unitPrice: price, discount: 0, vatPercent: 12 }],
        subtotal: price, discountTotal: 0, total: price,
        paidCash: price, paidCard: 0,
      },
    })
    expect([200, 201]).toContain(saleResp.status())
    const sale = await saleResp.json() as { id: string }
    const postResp = await ctx.post(`/api/sales/retail/${sale.id}/post`)
    expect([200, 204], `post status (${await postResp.text().catch(()=>'')})`).toContain(postResp.status())

    // Ждём live-обновления: счётчик чеков должен вырасти. Полагаемся на
    // refetch stats + liveCountDelta — что бы первое не отработало, второе
    // должно сразу прибавить +1.
    await expect(async () => {
      const hint = await page.locator('text=/\\d+\\s+чеков/').first().textContent()
      const cur = hint ? parseInt(hint, 10) : 0
      expect(cur).toBeGreaterThan(initial)
    }).toPass({ timeout: 15_000 })

    expectNoErrorsOptional(errs)
    await ctx.dispose()
  })
})

function expectNoErrorsOptional(errs: { console: string[]; network: string[] }) {
  // SignalR negotiate может вернуть 401 если token истёк — terпимо.
  const significant = errs.network.filter(s => !/\/hubs\/notifications/.test(s))
  if (significant.length || errs.console.length) {
    // eslint-disable-next-line no-console
    console.warn('[s8-signalr] non-fatal errors:', { console: errs.console, network: significant })
  }
}
