import { test, expect, APIRequestContext } from "@playwright/test"
import { ApiSeeder, newApiContext, Warehouse, Item, Vendor } from "../support/api"
import { ProductionRunListPage, ProductionRunDetailPage } from "../pages/ProductionRunPages"

// Production run lifecycle (Backend/ERPCore/Controllers/ProductionRunsController.cs,
// Frontend app/dashboard/production/runs/*). Uses a minimal single-stage template (one
// stage that is both entry and terminal - see ApiSeeder.createSingleStageTemplate) so the
// stage-action sequence (start -> complete -> approve & receive) is exercised without
// needing a multi-stage graph.
test.describe("Production runs", () => {
  let api: APIRequestContext
  let seeder: ApiSeeder
  let warehouse: Warehouse
  let vendor: Vendor
  let rawItem: Item
  let finishedItem: Item
  let templateName: string

  test.beforeAll(async () => {
    api = await newApiContext()
    seeder = new ApiSeeder(api)
    warehouse = await seeder.firstWarehouse()
    vendor = await seeder.createVendor()
    rawItem = await seeder.createItem({ namePrefix: "PROD Raw Material" })
    finishedItem = await seeder.createItem({ namePrefix: "PROD Finished Good" })

    // Give the run something to consume.
    await seeder.receiveStock({
      warehouseId: warehouse.warehouseId,
      vendorId: vendor.vendorId,
      itemId: rawItem.itemId,

      qty: 100,
      unitCost: 20,
    })

    const template = await seeder.createSingleStageTemplate({
      rawItemId: rawItem.itemId,
      finishedItemId: finishedItem.itemId,

    })
    templateName = template.name
  })

  test.afterAll(async () => {
    await api.dispose()
  })

  test("start run -> complete stage -> approve & receive posts finished-good stock", async ({ page }) => {
    const list = new ProductionRunListPage(page)
    await list.goto()
    await list.startRun({ template: templateName, targetQty: 10, warehouse: warehouse.name })

    await expect(page).toHaveURL(/\/dashboard\/production\/runs\/\d+/)
    const detail = new ProductionRunDetailPage(page)
    await detail.expectStatus(/in progress/i)

    await detail.openStage("Assemble")
    await detail.saveQuantities()
    await detail.startStage()

    const before = await seeder.stockOnHand(finishedItem.itemId, warehouse.warehouseId)

    await detail.completeStage({ producedQty: 10 })
    await detail.approveAndReceive()

    const after = await seeder.stockOnHand(finishedItem.itemId, warehouse.warehouseId)
    expect(after.onHand).toBeCloseTo(before.onHand + 10, 4)
  })

  test("cancel run stops further stage actions", async ({ page }) => {
    const list = new ProductionRunListPage(page)
    await list.goto()
    await list.startRun({ template: templateName, targetQty: 5, warehouse: warehouse.name })
    await expect(page).toHaveURL(/\/dashboard\/production\/runs\/\d+/)

    const detail = new ProductionRunDetailPage(page)
    await detail.cancelRun({ reason: "Production Run Cancelled", note: "E2E cancel test" })
    await detail.expectStatus(/cancelled/i)
  })

  test("return leftover raw material posts the unused quantity back to stock", async ({ page }) => {
    const list = new ProductionRunListPage(page)
    await list.goto()
    await list.startRun({ template: templateName, targetQty: 5, warehouse: warehouse.name })
    await expect(page).toHaveURL(/\/dashboard\/production\/runs\/\d+/)

    const detail = new ProductionRunDetailPage(page)
    await detail.openStage("Assemble")
    await detail.saveQuantities()
    await detail.startStage() // consumes the raw-material FIFO layers, making them returnable
    await detail.closeStageDrawer()

    const before = await seeder.stockOnHand(rawItem.itemId, warehouse.warehouseId)

    await detail.returnLeftover({ material: rawItem.name, qty: 1, reason: "Production Leftover Return" })

    const after = await seeder.stockOnHand(rawItem.itemId, warehouse.warehouseId)
    expect(after.onHand).toBeCloseTo(before.onHand + 1, 4)
  })

  test("reject for rework resets the run and increments the rework count", async ({ page }) => {
    const list = new ProductionRunListPage(page)
    await list.goto()
    await list.startRun({ template: templateName, targetQty: 5, warehouse: warehouse.name })
    await expect(page).toHaveURL(/\/dashboard\/production\/runs\/\d+/)

    const detail = new ProductionRunDetailPage(page)
    await detail.openStage("Assemble")
    await detail.saveQuantities()
    await detail.startStage()
    await detail.completeStage({ producedQty: 5 }) // stage -> Done, and terminal (single-stage template)

    await detail.rejectForRework()
    await detail.expectStatus(/rework #1/i)
  })
})
