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

const taskId = '00000000-0000-0000-0000-000000000101'

function task(stage: string, version: number, pickedQty = 0) {
  const completed = stage === 'completed'
  return {
    taskId,
    taskNo: 'PICK-20260808-001',
    stage,
    status: completed ? 'COMPLETED' : stage === 'ready' ? 'READY' : 'IN_PROGRESS',
    completedLines: completed ? 1 : 0,
    totalLines: 1,
    completedQty: completed ? 2 : pickedQty,
    totalQty: 2,
    version,
    currentLine: completed ? null : {
      lineId: '00000000-0000-0000-0000-000000000201',
      lineNo: 1,
      locationCode: 'A-03-02',
      itemId: '00000000-0000-0000-0000-000000000301',
      itemCode: 'ABC001',
      itemName: '운동화',
      itemOption: 'BLACK / 270',
      barcode: '8801234567890',
      requiredQty: 2,
      pickedQty,
      remainingQty: 2 - pickedQty,
    },
  }
}

test.describe('WMS-PICK-001 피킹 Golden Screen', () => {
  test('위치 → 상품 스캔을 확인 modal 없이 연속 처리한다', async ({ page }) => {
    let current = task('ready', 1)

    await page.route(`**/api/wms/picking/tasks/${taskId}`, route =>
      route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(current) }))

    await page.route(`**/api/wms/picking/tasks/${taskId}/start`, route => {
      current = task('await-location', 2)
      return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(current) })
    })

    await page.route(`**/api/wms/picking/tasks/${taskId}/scan`, async route => {
      const body = route.request().postDataJSON()
      if (body.barcode === 'LOC-A-03-02') {
        current = task('await-item', 3)
        return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({
          accepted: true, duplicate: false, task: current, feedback: 'success',
          message: '위치를 확인했습니다. 상품을 스캔하세요.',
        }) })
      }

      current = task('await-item', 4, 1)
      return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({
        accepted: true, duplicate: false, task: current, feedback: 'success', message: '1개 피킹했습니다.',
      }) })
    })

    await page.goto(`/wms/picking/${taskId}`)
    await expect(page.locator('[data-screen-id="WMS-PICK-001"]')).toBeVisible()

    await page.getByRole('button', { name: '작업 시작' }).click()
    await expect(page.getByText('위치를 스캔하세요.')).toBeVisible()

    // Keyboard-wedge scanners typically emit fast characters followed by Enter.
    await page.keyboard.type('LOC-A-03-02', { delay: 10 })
    await page.keyboard.press('Enter')
    await expect(page.getByText('상품을 스캔하세요.')).toBeVisible()

    await page.keyboard.type('8801234567890', { delay: 10 })
    await page.keyboard.press('Enter')
    await expect(page.getByText('1개 피킹했습니다.')).toBeVisible()
    await expect(page.getByText('남음').locator('..').getByText('1')).toBeVisible()
  })

  test('잘못된 위치는 retry queue 대상이 아닌 업무 오류로 즉시 안내한다', async ({ page }) => {
    let current = task('await-location', 2)

    await page.route(`**/api/wms/picking/tasks/${taskId}`, route =>
      route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(current) }))

    await page.route(`**/api/wms/picking/tasks/${taskId}/scan`, route =>
      route.fulfill({ status: 422, contentType: 'application/json', body: JSON.stringify({
        accepted: false, duplicate: false, task: current, feedback: 'error',
        message: '잘못된 위치입니다. A-03-02 위치로 이동하세요.',
      }) }))

    await page.goto(`/wms/picking/${taskId}`)
    await page.keyboard.type('WRONG-LOC', { delay: 10 })
    await page.keyboard.press('Enter')

    await expect(page.getByText('잘못된 위치입니다. A-03-02 위치로 이동하세요.')).toBeVisible()
    await expect(page.getByText('전송 대기')).toHaveCount(0)
  })

  test('오프라인이면 다음 authoritative scan을 받지 않는다', async ({ page, context }) => {
    await page.route(`**/api/wms/picking/tasks/${taskId}`, route =>
      route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(task('await-item', 3)) }))

    await page.goto(`/wms/picking/${taskId}`)
    await context.setOffline(true)
    await page.evaluate(() => window.dispatchEvent(new Event('offline')))

    await expect(page.getByText(/오프라인/)).toBeVisible()
    await expect(page.getByText('SCAN PAUSED')).toBeVisible()
  })
})

test.describe('WMS-PICK-001 authoritative retry evidence', () => {
  test('response loss 재전송은 최초 command의 동일 idempotencyKey를 사용하고 서버 확인 뒤에만 최근 확인을 갱신한다', async ({ page, context }) => {
    let current = task('await-item', 3)
    const scanBodies: Array<Record<string, unknown>> = []

    await page.route(`**/api/wms/picking/tasks/${taskId}`, route =>
      route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(current) }))

    await page.route(`**/api/wms/picking/tasks/${taskId}/scan`, async route => {
      const body=route.request().postDataJSON() as Record<string, unknown>
      scanBodies.push(body)
      if(scanBodies.length===1) return route.abort('failed')
      current=task('await-item',4,1)
      return route.fulfill({
        status:200,
        contentType:'application/json',
        body:JSON.stringify({accepted:true,duplicate:true,task:current,feedback:'success',message:'재전송된 스캔을 서버에서 확인했습니다.'}),
      })
    })

    await page.goto(`/wms/picking/${taskId}`)
    await page.keyboard.type('8801234567890', { delay: 10 })
    await page.keyboard.press('Enter')

    await expect(page.getByText(/서버 확인이 필요합니다/)).toBeVisible()
    await expect(page.getByText('아직 확인된 스캔 없음')).toBeVisible()

    await context.setOffline(true)
    await page.evaluate(() => window.dispatchEvent(new Event('offline')))
    await context.setOffline(false)
    await page.evaluate(() => window.dispatchEvent(new Event('online')))

    await expect.poll(() => scanBodies.length).toBe(2)
    expect(scanBodies[0]?.idempotencyKey).toBeTruthy()
    expect(scanBodies[1]?.idempotencyKey).toBe(scanBodies[0]?.idempotencyKey)
    await expect(page.getByText(/재전송된 스캔을 서버에서 확인했습니다/)).toBeVisible()
    await expect(page.getByText(/8801234567890/)).toBeVisible()
  })
})
