import { NextRequest, NextResponse } from 'next/server';
import prisma from '@/lib/db';
import { withPermission, isErrorResponse } from '@/lib/auth/api-guard';
import { handleError } from '@/lib/errors';

export const dynamic = 'force-dynamic';

// Default reorder threshold if product doesn't have one set
const DEFAULT_REORDER_LEVEL = 10;

/**
 * Determines stock status based on quantity and product-specific reorder level
 */
function getStockStatus(quantity: number, reorderLevel?: number | null): string {
  if (quantity === 0) return 'out-of-stock';
  const threshold = reorderLevel ?? DEFAULT_REORDER_LEVEL;
  return quantity < threshold ? 'low-stock' : 'in-stock';
}

// GET - Fetch inventory data
export async function GET(request: NextRequest) {
  const auth = await withPermission(request, { resource: 'inventory', action: 'read' });
  if (isErrorResponse(auth)) return auth;

  try {
    const { searchParams } = new URL(request.url);
    const type = searchParams.get('type') || 'summary';

    if (type === 'products') {
      const products = await prisma.product.findMany({
        where: { isActive: true },
        include: {
          supplier: { select: { name: true, code: true } },
          inventoryItems: true,
        },
        orderBy: { name: 'asc' },
      });
      return NextResponse.json({ success: true, products });
    }

    if (type === 'suppliers') {
      const suppliers = await prisma.supplier.findMany({
        where: { status: 'active' },
        include: { _count: { select: { products: true, purchaseOrders: true } } },
        orderBy: { name: 'asc' },
      });
      return NextResponse.json({ success: true, suppliers });
    }

    if (type === 'stock') {
      const inventory = await prisma.inventoryItem.findMany({
        include: { product: { select: { sku: true, name: true, reorderLevel: true } } },
        orderBy: { updatedAt: 'desc' },
      });
      return NextResponse.json({ success: true, inventory });
    }

    if (type === 'movements') {
      const movements = await prisma.stockMovement.findMany({
        include: { product: { select: { sku: true, name: true } } },
        orderBy: { createdAt: 'desc' },
        take: 100,
      });
      return NextResponse.json({ success: true, movements });
    }

    if (type === 'purchase-orders') {
      const purchaseOrders = await prisma.purchaseOrder.findMany({
        include: {
          supplier: { select: { name: true } },
          items: { include: { product: { select: { name: true, sku: true } } } },
        },
        orderBy: { orderDate: 'desc' },
        take: 50,
      });
      return NextResponse.json({ success: true, purchaseOrders });
    }

    // Summary
    const [products, inventory, lowStock, pendingOrders, recentMovements] = await Promise.all([
      prisma.product.findMany({ where: { isActive: true } }),
      prisma.inventoryItem.findMany(),
      prisma.inventoryItem.findMany({ 
        where: { status: { in: ['low-stock', 'out-of-stock'] } },
        include: { product: { select: { sku: true, name: true, reorderLevel: true } } }
      }),
      prisma.purchaseOrder.findMany({ where: { status: { in: ['draft', 'sent', 'confirmed'] } } }),
      prisma.stockMovement.findMany({ 
        take: 10, 
        orderBy: { createdAt: 'desc' },
        include: { product: { select: { sku: true, name: true } } }
      }),
    ]);

    const totalProducts = products.length;
    const totalStock = inventory.reduce((sum: number, i: any) => sum + i.quantity, 0);
    
    // PERFORMANCE FIX: Use Map for O(1) lookup instead of O(n) find
    // Previous: O(n²) - for each product, scan all inventory items
    // Now: O(n) - build map once, then O(1) lookups
    const inventoryMap = new Map(inventory.map((i: any) => [i.productId, i]));
    const stockValue = products.reduce((sum: number, p: any) => {
      const item: any = inventoryMap.get(p.id);
      return sum + (item ? item.quantity * (p.costPrice || 0) : 0);
    }, 0);

    // Filter out any records with missing product relations
    const validLowStock = lowStock.filter((item: any) => item.product && item.product.name);
    const validMovements = recentMovements.filter((item: any) => item.product && item.product.name);

    return NextResponse.json({
      success: true,
      summary: {
        totalProducts,
        totalStock,
        stockValue,
        lowStockCount: validLowStock.length,
        outOfStockCount: inventory.filter((i: any) => i.status === 'out-of-stock').length,
        pendingOrdersCount: pendingOrders.length,
        pendingOrdersValue: pendingOrders.reduce((sum: number, o: any) => sum + (o.total || 0), 0),
        locations: [...new Set(inventory.map((i: any) => i.location))].length,
      },
      lowStockAlerts: validLowStock.slice(0, 5),
      recentMovements: validMovements.slice(0, 5),
      pendingOrders: pendingOrders.slice(0, 5),
    });
  } catch (error) {
    console.error('Inventory API error:', error);
    return handleError(error);
  }
}

// POST - Create new product/supplier/movement/PO
export async function POST(request: NextRequest) {
  const auth = await withPermission(request, { resource: 'inventory', action: 'write' });
  if (isErrorResponse(auth)) return auth;

  try {
    const body = await request.json();
    const { entity, data } = body;

    if (entity === 'product') {
      const product = await prisma.product.create({ data });
      // Create initial inventory item
      await prisma.inventoryItem.create({
        data: {
          productId: product.id,
          quantity: 0,
          availableQty: 0,
          status: 'out-of-stock',
        },
      });
      return NextResponse.json({ success: true, product });
    }

    if (entity === 'supplier') {
      const supplier = await prisma.supplier.create({ data });
      return NextResponse.json({ success: true, supplier });
    }

    if (entity === 'stock-movement') {
      const movement = await prisma.stockMovement.create({ data });
      
      // Get product for reorder level
      const product = await prisma.product.findUnique({ 
        where: { id: data.productId },
        select: { reorderLevel: true }
      });
      
      // Update inventory
      const qtyChange = data.type === 'in' ? data.quantity : -data.quantity;
      const inventory = await prisma.inventoryItem.findFirst({
        where: { productId: data.productId, location: data.toLocation || 'main-warehouse' },
      });
      
      if (inventory) {
        const newQty = Math.max(0, inventory.quantity + qtyChange);
        await prisma.inventoryItem.update({
          where: { id: inventory.id },
          data: {
            quantity: newQty,
            availableQty: newQty - inventory.reservedQty,
            status: getStockStatus(newQty, product?.reorderLevel),
            lastRestocked: data.type === 'in' ? new Date() : undefined,
          },
        });
      }
      return NextResponse.json({ success: true, movement });
    }

    if (entity === 'purchase-order') {
      const po = await prisma.purchaseOrder.create({
        data: {
          ...data,
          items: { create: data.items },
        },
        include: { items: true },
      });
      return NextResponse.json({ success: true, purchaseOrder: po });
    }

    return NextResponse.json({ success: false, error: 'Invalid entity type' }, { status: 400 });
  } catch (error) {
    console.error('Inventory POST error:', error);
    return handleError(error);
  }
}

// PATCH - Update PO status, receive goods, etc
export async function PATCH(request: NextRequest) {
  const auth = await withPermission(request, { resource: 'inventory', action: 'write' });
  if (isErrorResponse(auth)) return auth;

  try {
    const body = await request.json();
    const { entity, id, data } = body;

    if (entity === 'purchase-order') {
      const po = await prisma.purchaseOrder.update({
        where: { id },
        data,
        include: { items: { include: { product: true } } },
      });
      
      // If received, update inventory
      if (data.status === 'received') {
        for (const item of po.items) {
          await prisma.stockMovement.create({
            data: {
              productId: item.productId,
              type: 'in',
              quantity: item.quantity,
              reference: po.orderNumber,
              reason: 'Purchase Order Received',
            },
          });
          
          const inventory = await prisma.inventoryItem.findFirst({
            where: { productId: item.productId },
          });
          if (inventory) {
            const newQty = inventory.quantity + item.quantity;
            // Use product-specific reorder level instead of hardcoded 10
            await prisma.inventoryItem.update({
              where: { id: inventory.id },
              data: {
                quantity: newQty,
                availableQty: newQty - inventory.reservedQty,
                status: getStockStatus(newQty, (item as any).product?.reorderLevel),
                lastRestocked: new Date(),
              },
            });
          }
        }
      }
      return NextResponse.json({ success: true, purchaseOrder: po });
    }

    if (entity === 'product') {
      const product = await prisma.product.update({
        where: { id },
        data,
      });
      return NextResponse.json({ success: true, product });
    }

    return NextResponse.json({ success: false, error: 'Invalid entity type' }, { status: 400 });
  } catch (error) {
    console.error('Inventory PATCH error:', error);
    return handleError(error);
  }
}
