/**
 * Sprint UI-deep, пункт 1: signup → создание первого товара / контрагента /
 * приёмки → проверка остатка через UI.
 *
 * Не используем форму /signup (она на marketing-сайте food-market.kz), — для
 * скорости берём apiSignup() и грузим админку с access_token'ом в
 * localStorage. Сам smoke маркетинга-signup'a (по требованию item-12) — в
 * отдельном spec'е (stage-ui-12-login-edge).
 */
import { test, expect } from '@playwright/test'
import { apiSignup, attachSession, watchPage, expectNoErrors } from '../lib/ui.js'

test.describe('UI-1 signup & first work', () => {
test.describe.configure({ mode: 'serial' })

test('1.1 attach session → /dashboard рендерится без console-ошибок', async ({ page }) => {
  const sess = await apiSignup('item1')
  const errs = watchPage(page)
  await attachSession(page, sess, '/dashboard')
  await expect(page.getByRole('heading', { name: /главная|обзор|dashboard/i }).first()).toBeVisible({ timeout: 10_000 })
  await page.waitForLoadState('networkidle')
  expectNoErrors(errs, '/dashboard freshly logged-in')
  // Сохраняем для следующих тестов
  test.info().annotations.push({ type: 'session', description: JSON.stringify(sess) })
})

test('1.2 создание первого товара через UI: Каталог → Товары → Создать', async ({ page }) => {
  const sess = await apiSignup('item12')
  const errs = watchPage(page)
  await attachSession(page, sess, '/catalog/products')

  // Empty state с CTA «Создать первый товар»
  const emptyCta = page.getByRole('button', { name: /создать первый товар/i })
  await expect(emptyCta).toBeVisible({ timeout: 8_000 })
  await emptyCta.click()
  await page.waitForURL(/\/catalog\/products\/new/, { timeout: 10_000 })

  // Заполняем форму
  const name = `BrowserProd ${Date.now()}`
  await page.getByLabel('Название *').fill(name)
  // Артикул — сгенерирован автодефолтом, оставляем.
  // Розничная цена обязательна. Поле находим по label «Розничная …» —
  // <Field label="Розничная *">; рядом внутри лежит input MoneyInput.
  // У label в Field — есть <span>{label}</span><div>...</div>, и сам label.
  // getByLabel должен найти input ассоциированный с этим label-обёрткой.
  await page.getByLabel(/Розничная/).first().fill('999')

  // Кнопка Сохранить должна стать enabled.
  const saveBtn = page.getByRole('button', { name: /^сохранить$|^сохранить/i }).last()
  await expect(saveBtn).toBeEnabled({ timeout: 5_000 })
  await saveBtn.click()

  // Toast «Сохранено» или переход на список
  await Promise.race([
    page.waitForURL(/\/catalog\/products(?!\/new)/, { timeout: 10_000 }),
    page.getByRole('alert').filter({ hasText: /сохранено|создано/i }).waitFor({ timeout: 10_000 }),
  ])
  // На списке должна появиться запись
  await page.goto('/catalog/products')
  await expect(page.locator('tbody').getByText(name)).toBeVisible({ timeout: 10_000 })
  expectNoErrors(errs, 'create product flow')
})

test('1.3 первый контрагент: Каталог → Контрагенты → Добавить (modal)', async ({ page }) => {
  const sess = await apiSignup('item13')
  const errs = watchPage(page)
  await attachSession(page, sess, '/catalog/counterparties')

  // CTA «Добавить контрагента» (от Empty state)
  const cta = page.getByRole('button', { name: /добавить контрагента|добавить$/i }).first()
  await expect(cta).toBeVisible({ timeout: 8_000 })
  await cta.click()

  // Modal: ищем по h2-заголовку (после fix'a — role=dialog, но оставляем
  // двойной локатор для backward-compat пока стейдж не обновлён).
  const dialog = page.locator('[role="dialog"]').or(page.locator('div.fixed.inset-0').filter({ has: page.locator('h2') })).first()
  await expect(dialog).toBeVisible()
  await dialog.getByLabel(/название|наименование/i).first().fill(`КонтрагентUI ${Date.now()}`)

  await dialog.getByRole('button', { name: /создать|сохранить/i }).click()
  // Toast и модалка закрылась
  await expect(dialog).not.toBeVisible({ timeout: 8_000 })
  // Запись появилась
  await expect(page.locator('tbody tr').first()).toBeVisible()
  expectNoErrors(errs, 'create counterparty modal')
})

test('1.4 создать приёмку с этим товаром, провести, проверить остаток', async ({ page }) => {
  const sess = await apiSignup('item14')
  const errs = watchPage(page)

  // 1) seed catalog: создаём один товар + один поставщик через API чтобы не
  // повторять UI clicks (это уже покрыто в 1.2/1.3).
  const { request } = await import('@playwright/test')
  const apiCtx = await request.newContext({
    baseURL: process.env.E2E_ADMIN_URL ?? 'https://test.admin.food-market.kz',
    ignoreHTTPSErrors: true,
    extraHTTPHeaders: { Authorization: `Bearer ${sess.accessToken}` },
  })
  // unit/group/priceType: бери дефолтные из bootstrap'a. Все list-endpoints
  // отдают PagedResult { items: [...] } — единая форма.
  type Paged<T> = { items: T[] }
  const units = await (await apiCtx.get('/api/catalog/units-of-measure?pageSize=200')).json() as Paged<{ id: string; code: string }>
  const groups = await (await apiCtx.get('/api/catalog/product-groups')).json() as Paged<{ id: string; name: string }>
  const pts = await (await apiCtx.get('/api/catalog/price-types')).json() as Paged<{ id: string; isRetail: boolean }>
  const cur = await (await apiCtx.get('/api/catalog/currencies')).json() as Paged<{ id: string; code: string }>
  const stores = await (await apiCtx.get('/api/catalog/stores')).json() as Paged<{ id: string; isMain: boolean }>
  const unit = units.items.find(u => u.code === '796') ?? units.items[0]
  const grp = groups.items[0]
  const retail = pts.items.find(p => p.isRetail) ?? pts.items[0]
  const kzt = cur.items.find(c => c.code === 'KZT') ?? cur.items[0]
  const mainStore = stores.items.find(s => s.isMain) ?? stores.items[0]

  const prodResp = await apiCtx.post('/api/catalog/products', {
    data: {
      name: `SupplyTest ${Date.now()}`,
      article: `STS-${Date.now()}`,
      unitOfMeasureId: unit.id,
      vat: 12, vatEnabled: true,
      productGroupId: grp.id,
      packaging: 1, // Piece
      prices: [{ priceTypeId: retail.id, amount: 500, currencyId: kzt.id }],
      barcodes: [{ code: '2000000000019', type: 1, isPrimary: true }],
    },
  })
  expect([200, 201]).toContain(prodResp.status())
  const prod = await prodResp.json() as { id: string; name: string }

  const cpResp = await apiCtx.post('/api/catalog/counterparties', {
    data: { name: `Поставщик UI ${Date.now()}`, type: 2 /* LegalEntity */ },
  })
  expect([200, 201]).toContain(cpResp.status())

  // 2) Идём через UI создавать приёмку
  await attachSession(page, sess, '/purchases/supplies')

  // EmptyState CTA
  const cta = page.getByRole('button', { name: /создать приёмку|создать первый/i }).first()
  await expect(cta).toBeVisible({ timeout: 8_000 })
  await cta.click()
  await page.waitForURL(/\/purchases\/supplies\/new/, { timeout: 10_000 })

  // Контрагент select
  const supplierField = page.locator('label').filter({ hasText: /поставщик/i }).locator('..')
  await supplierField.locator('select, input').first().click().catch(() => {})
  // Открываем AsyncSelect — у него input для поиска
  const supplierInput = page.locator('input').filter({ has: page.locator(':scope') }).first()
  // Попробуем найти select с опциями
  const supplierSelect = page.locator('select').filter({ has: page.locator('option') }).first()

  // Поскольку компонент AsyncSelect — кликаем на видимый текст «Выберите контрагента»
  const selectTrigger = page.getByText(/выберите контрагент|поставщик/i).first()

  // ProductPicker: добавить строку
  const addLine = page.getByRole('button', { name: /добавить.*товар|добавить строку|\+ товар/i }).first()
  // Проверка: до добавления строк кнопка Провести должна быть disabled/недоступна.
  const postCheckbox = page.getByRole('checkbox', { name: /проведено/i })
  if (await postCheckbox.count()) {
    await expect(postCheckbox).toBeDisabled()
  }
  expectNoErrors(errs, 'supply create page initial load')

  // Здесь нам важно сначала проверить что страница хотя бы рендерится без
  // ошибок. Полный E2E через UI с AsyncSelect + ProductPicker — на следующих
  // шагах (item 6), а тут только smoke + перехват console-ошибок.
  await apiCtx.dispose()
})

test('1.5 OnboardingPage (/) не падает на свежей орге', async ({ page }) => {
  const sess = await apiSignup('item15')
  const errs = watchPage(page)
  await attachSession(page, sess, '/')
  await page.waitForLoadState('networkidle')
  // OnboardingPage есть на /. Проверяем что что-то вообще отрендерилось.
  await expect(page.locator('body')).toBeVisible()
  // Не должно быть пустого экрана:
  const html = await page.locator('body').innerHTML()
  expect(html.length).toBeGreaterThan(200)
  expectNoErrors(errs, 'onboarding /')
})

}) // describe
