import type { FastifyPluginAsync } from 'fastify'
import {
  ProductCreateSchema,
  ProductUpdateSchema,
  InventoryUnitCreateSchema,
  InventoryUnitUpdateSchema,
  ProductSupplierCreateSchema,
  ProductSupplierUpdateSchema,
  StockReceiptCreateSchema,
  PaginationSchema,
} from '@lunarfront/shared/schemas'
import { ProductService, InventoryUnitService, ProductSupplierService, StockReceiptService } from '../../services/product.service.js'

export const productRoutes: FastifyPluginAsync = async (app) => {
  // --- UPC Barcode Lookup ---

  app.get('/products/lookup/upc/:upc', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const { upc } = request.params as { upc: string }
    const product = await ProductService.getByUpc(app.db, upc)
    if (!product) return reply.status(404).send({ error: { message: 'No product found for this UPC', statusCode: 404 } })
    return reply.send(product)
  })

  // --- Products ---

  app.post('/products', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const parsed = ProductCreateSchema.safeParse(request.body)
    if (!parsed.success) {
      return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
    }
    const product = await ProductService.create(app.db, parsed.data)
    return reply.status(201).send(product)
  })

  app.get('/products', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const params = PaginationSchema.parse(request.query)
    const q = request.query as Record<string, string>
    const filters = {
      categoryId: q.categoryId,
      isActive: q.isActive === 'true' ? true : q.isActive === 'false' ? false : undefined,
      isSerialized: q.isSerialized === 'true' ? true : q.isSerialized === 'false' ? false : undefined,
      isRental: q.isRental === 'true' ? true : q.isRental === 'false' ? false : undefined,
      isDualUseRepair: q.isDualUseRepair === 'true' ? true : q.isDualUseRepair === 'false' ? false : undefined,
      isConsumable: q.isConsumable === 'true' ? true : q.isConsumable === 'false' ? false : undefined,
      lowStock: q.lowStock === 'true',
    }
    const result = await ProductService.list(app.db, params, filters)
    return reply.send(result)
  })

  app.get('/products/:id', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const { id } = request.params as { id: string }
    const product = await ProductService.getById(app.db, id)
    if (!product) return reply.status(404).send({ error: { message: 'Product not found', statusCode: 404 } })
    return reply.send(product)
  })

  app.patch('/products/:id', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const { id } = request.params as { id: string }
    const parsed = ProductUpdateSchema.safeParse(request.body)
    if (!parsed.success) {
      return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
    }
    const product = await ProductService.update(app.db, id, parsed.data, request.user.id)
    if (!product) return reply.status(404).send({ error: { message: 'Product not found', statusCode: 404 } })
    return reply.send(product)
  })

  app.delete('/products/:id', { preHandler: [app.authenticate, app.requirePermission('inventory.admin')] }, async (request, reply) => {
    const { id } = request.params as { id: string }
    const product = await ProductService.softDelete(app.db, id)
    if (!product) return reply.status(404).send({ error: { message: 'Product not found', statusCode: 404 } })
    return reply.send(product)
  })

  // --- Inventory Units ---

  app.post('/products/:productId/units', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const { productId } = request.params as { productId: string }
    const parsed = InventoryUnitCreateSchema.safeParse({ ...(request.body as object), productId })
    if (!parsed.success) {
      return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
    }
    const unit = await InventoryUnitService.create(app.db, parsed.data)
    return reply.status(201).send(unit)
  })

  app.get('/products/:productId/units', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const { productId } = request.params as { productId: string }
    const params = PaginationSchema.parse(request.query)
    const result = await InventoryUnitService.listByProduct(app.db, productId, params)
    return reply.send(result)
  })

  app.get('/units/:id', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const { id } = request.params as { id: string }
    const unit = await InventoryUnitService.getById(app.db, id)
    if (!unit) return reply.status(404).send({ error: { message: 'Unit not found', statusCode: 404 } })
    return reply.send(unit)
  })

  app.patch('/units/:id', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const { id } = request.params as { id: string }
    const parsed = InventoryUnitUpdateSchema.safeParse(request.body)
    if (!parsed.success) {
      return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
    }
    const unit = await InventoryUnitService.update(app.db, id, parsed.data)
    if (!unit) return reply.status(404).send({ error: { message: 'Unit not found', statusCode: 404 } })
    return reply.send(unit)
  })

  // --- Product Suppliers ---

  app.get('/products/:productId/suppliers', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const { productId } = request.params as { productId: string }
    const rows = await ProductSupplierService.listByProduct(app.db, productId)
    return reply.send({ data: rows })
  })

  app.post('/products/:productId/suppliers', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const { productId } = request.params as { productId: string }
    const parsed = ProductSupplierCreateSchema.safeParse(request.body)
    if (!parsed.success) {
      return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
    }
    const row = await ProductSupplierService.create(app.db, productId, parsed.data)
    return reply.status(201).send(row)
  })

  app.patch('/products/:productId/suppliers/:id', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const { productId, id } = request.params as { productId: string; id: string }
    const parsed = ProductSupplierUpdateSchema.safeParse(request.body)
    if (!parsed.success) {
      return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
    }
    const row = await ProductSupplierService.update(app.db, id, productId, parsed.data)
    if (!row) return reply.status(404).send({ error: { message: 'Not found', statusCode: 404 } })
    return reply.send(row)
  })

  app.delete('/products/:productId/suppliers/:id', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const { id } = request.params as { id: string }
    const row = await ProductSupplierService.delete(app.db, id)
    if (!row) return reply.status(404).send({ error: { message: 'Not found', statusCode: 404 } })
    return reply.send(row)
  })

  // --- Price History ---

  app.get('/products/:productId/price-history', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const { productId } = request.params as { productId: string }
    const rows = await ProductService.listPriceHistory(app.db, productId)
    return reply.send({ data: rows })
  })

  // --- Stock Receipts ---

  app.post('/products/:productId/stock-receipts', { preHandler: [app.authenticate, app.requirePermission('inventory.edit')] }, async (request, reply) => {
    const { productId } = request.params as { productId: string }
    const parsed = StockReceiptCreateSchema.safeParse(request.body)
    if (!parsed.success) {
      return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
    }
    const receipt = await StockReceiptService.create(app.db, productId, parsed.data)
    return reply.status(201).send(receipt)
  })

  app.get('/products/:productId/stock-receipts', { preHandler: [app.authenticate, app.requirePermission('inventory.view')] }, async (request, reply) => {
    const { productId } = request.params as { productId: string }
    const rows = await StockReceiptService.listByProduct(app.db, productId)
    return reply.send({ data: rows })
  })
}
