<?php
require_once __DIR__ . '/functions.php';

/**
 * Reserves inventory stock based on the production line's total target quantity.
 */
function reserveProductionStock($productionLineId) {
    global $pdo;
    
    // Check if already reserved
    $line = fetch("SELECT is_stock_reserved FROM production_lines WHERE id = ?", [$productionLineId]);
    if (!$line || $line['is_stock_reserved']) return ['success' => true, 'message' => 'Already reserved or line not found.'];

    // Fetch all materials required for the ENTIRE production run
    $materials = fetchAll("
        SELECT 
            iip.inventory_item_id, 
            iip.quantity as material_qty_per_unit, 
            iip.wastage_quantity as wastage_qty_per_unit,
            plp.quantity as product_line_target
        FROM production_line_products plp
        JOIN inventory_item_product iip ON plp.product_id = iip.product_id
        WHERE plp.production_line_id = ?
    ", [$productionLineId]);

    if (empty($materials)) {
        return ['success' => true, 'message' => 'No materials to reserve.'];
    }

    // Group by material ID to get total requirements
    $requirements = [];
    foreach ($materials as $m) {
        $itemId = $m['inventory_item_id'];
        $needed = ($m['material_qty_per_unit'] + $m['wastage_qty_per_unit']) * $m['product_line_target'];
        
        if (!isset($requirements[$itemId])) {
            $requirements[$itemId] = 0;
        }
        $requirements[$itemId] += $needed;
    }

    // Check availability for all materials
    foreach ($requirements as $itemId => $amount) {
        $item = fetch("SELECT name, stock, reserved_stock, unit FROM inventory_items WHERE id = ?", [$itemId]);
        $available = (float)$item['stock'] - (float)$item['reserved_stock'];
        if ($available < $amount) {
            throw new Exception("Insufficient stock for '{$item['name']}'. Needed: " . number_format($amount, 2) . ", Available: " . number_format($available, 2) . " " . $item['unit']);
        }
    }

    foreach ($requirements as $itemId => $amount) {
        // Deduct from stock and add to reserved_stock
        query("UPDATE inventory_items SET stock = stock - ?, reserved_stock = reserved_stock + ? WHERE id = ?", [$amount, $amount, $itemId]);
        checkInventoryStockAlert($itemId);
    }

    query("UPDATE production_lines SET is_stock_reserved = 1 WHERE id = ?", [$productionLineId]);
    logAudit('STOCK_RESERVED', "Reserved materials for Production Line ID: $productionLineId.");

    return ['success' => true, 'message' => 'Materials reserved successfully.'];
}

/**
 * Unreserves inventory stock when production finishes.
 */
function unreserveProductionStock($productionLineId) {
    global $pdo;
    
    // Check if reserved
    $line = fetch("SELECT is_stock_reserved FROM production_lines WHERE id = ?", [$productionLineId]);
    if (!$line || !$line['is_stock_reserved']) return ['success' => true, 'message' => 'Not reserved or line not found.'];

    // Calculate the same requirements again to unreserve
    $materials = fetchAll("
        SELECT 
            iip.inventory_item_id, 
            iip.quantity as material_qty_per_unit, 
            iip.wastage_quantity as wastage_qty_per_unit,
            plp.quantity as product_line_target
        FROM production_line_products plp
        JOIN inventory_item_product iip ON plp.product_id = iip.product_id
        WHERE plp.production_line_id = ?
    ", [$productionLineId]);

    $requirements = [];
    foreach ($materials as $m) {
        $itemId = $m['inventory_item_id'];
        $needed = ($m['material_qty_per_unit'] + $m['wastage_qty_per_unit']) * $m['product_line_target'];
        
        if (!isset($requirements[$itemId])) {
            $requirements[$itemId] = 0;
        }
        $requirements[$itemId] += $needed;
    }

    foreach ($requirements as $itemId => $amount) {
        // Remove from reserved_stock and ADD BACK to stock (deductProductionStock will then deduct the actual usage)
        query("UPDATE inventory_items SET reserved_stock = GREATEST(0, reserved_stock - ?), stock = stock + ? WHERE id = ?", [$amount, $amount, $itemId]);
        checkInventoryStockAlert($itemId);
    }

    query("UPDATE production_lines SET is_stock_reserved = 0 WHERE id = ?", [$productionLineId]);
    return ['success' => true];
}

/**
 * Deducts inventory stock based on the production line's output at Stage 1.
 * This logic follows the Bill of Materials (BOM) for each product on the line.
 */
function deductProductionStock($productionLineId, $userId = null) {

    global $pdo;
    
    try {
        // 1. Get the completion details from the first stage (Stage 1)
        $firstStage = fetch("
            SELECT completed_units, quantity as target_units 
            FROM line_stages 
            WHERE production_line_id = ? 
            ORDER BY sort_order ASC 
            LIMIT 1
        ", [$productionLineId]);
        
        if (!$firstStage) return ['success' => false, 'message' => 'First stage not found for this production line.'];
        
        $completedUnits = (int)$firstStage['completed_units'];
        if ($completedUnits <= 0) return ['success' => true, 'message' => 'No units completed at the first stage, no stock deducted.'];

        // 2. Get total target quantity for the whole production line across all products
        $lineTotal = fetch("
            SELECT SUM(quantity) as total_target 
            FROM production_line_products 
            WHERE production_line_id = ?
        ", [$productionLineId]);
        
        $totalTarget = (int)($lineTotal['total_target'] ?: 1);
        $completionFactor = $completedUnits / $totalTarget;

        // 3. Fetch all materials required
        $materials = fetchAll("
            SELECT 
                iip.inventory_item_id, 
                iip.quantity as material_qty_per_unit, 
                iip.wastage_quantity as wastage_qty_per_unit,
                plp.quantity as product_line_target
            FROM production_line_products plp
            JOIN inventory_item_product iip ON plp.product_id = iip.product_id
            WHERE plp.production_line_id = ?
        ", [$productionLineId]);

        if (empty($materials)) {
            return ['success' => true, 'message' => 'No materials linked to products on this line.'];
        }

        // 4. Group by material ID
        $deductions = [];
        foreach ($materials as $m) {
            $itemId = $m['inventory_item_id'];
            $totalPerProduct = ($m['material_qty_per_unit'] + $m['wastage_qty_per_unit']) * ($m['product_line_target'] * $completionFactor);
            
            if (!isset($deductions[$itemId])) {
                $deductions[$itemId] = 0;
            }
            $deductions[$itemId] += $totalPerProduct;
        }

        // 5. Execute stock updates and audit logging
        
        // Fetch user info for audit logging
        $userName = 'System';
        $userRole = 'System';
        if ($userId) {
            $u = fetch("
                SELECT e.name as emp_name, r.name as role_name 
                FROM users usr
                LEFT JOIN employees e ON usr.id = e.user_id
                LEFT JOIN roles r ON e.role_id = r.id
                WHERE usr.id = ?
            ", [$userId]);
            if ($u) {
                $userName = $u['emp_name'] ?: 'User #' . $userId;
                $userRole = $u['role_name'] ?: 'Manager';
            }
        }

        // Save main completion log
        query("INSERT INTO production_completion_logs (production_line_id, completed_units, completion_ratio, user_id, created_at) VALUES (?, ?, ?, ?, NOW())", [
            $productionLineId, $completedUnits, $completionFactor, $userId
        ]);
        $logId = $pdo->lastInsertId();

        foreach ($deductions as $itemId => $amount) {
            // Deduct stock
            query("UPDATE inventory_items SET stock = stock - ? WHERE id = ?", [$amount, $itemId]);
            
            // Log material deduction
            query("INSERT INTO production_completion_materials (completion_log_id, inventory_item_id, deducted_qty) VALUES (?, ?, ?)", [
                $logId, $itemId, $amount
            ]);
            checkInventoryStockAlert($itemId);
        }
        
        // General audit log entry
        logAudit('PRODUCTION_COMPLETED', "Finalized Production Line ID: $productionLineId. Log ID: $logId.");

        return ['success' => true, 'message' => 'Stock deducted and audit logs saved successfully.'];

    } catch (Exception $e) {
        throw $e; // Throw to be caught by caller transaction
    }
}

/**
 * Checks an inventory item's stock level and creates/resolves notifications as appropriate.
 */
function checkInventoryStockAlert($itemId) {
    $item = fetch("SELECT id, name, sku, stock, min_level, company_id, unit FROM inventory_items WHERE id = ?", [$itemId]);
    if (!$item) return;

    $companyId = $item['company_id'];
    
    // Check if notifications module is enabled for this company
    $company = fetch("SELECT enabled_modules FROM companies WHERE id = ?", [$companyId]);
    if (!$company) return;
    $enabled_modules = json_decode($company['enabled_modules'], true) ?: [];
    if (!in_array('notifications', $enabled_modules)) {
        return;
    }

    $stock = (float)$item['stock'];
    $minLevel = (float)$item['min_level'];
    $name = $item['name'];
    $sku = $item['sku'];
    $unit = $item['unit'];

    // Unique keys for deduplication
    $outKey = "inv_out_" . $itemId;
    $lowKey = "inv_low_" . $itemId;

    if ($stock <= 0) {
        // Create OUT OF STOCK notification
        createNotification(
            $companyId,
            'inventory',
            'Out of Stock Alert',
            "Material '{$name}' (SKU: {$sku}) is OUT OF STOCK!",
            '/inventory',
            $outKey
        );
        // Mark low stock notification as read/resolved if it exists
        query("UPDATE system_notifications SET is_read = 1 WHERE company_id = ? AND reference_key = ?", [$companyId, $lowKey]);
    } elseif ($stock <= $minLevel) {
        // Create LOW STOCK notification
        createNotification(
            $companyId,
            'inventory',
            'Low Stock Alert',
            "Material '{$name}' (SKU: {$sku}) is low on stock (Current: " . number_format($stock, 2) . " {$unit}).",
            '/inventory',
            $lowKey
        );
        // Mark out of stock notification as read/resolved if it exists (e.g. if restocked slightly)
        query("UPDATE system_notifications SET is_read = 1 WHERE company_id = ? AND reference_key = ?", [$companyId, $outKey]);
    } else {
        // Stock is healthy. Resolve both notifications automatically.
        query("UPDATE system_notifications SET is_read = 1 WHERE company_id = ? AND (reference_key = ? OR reference_key = ?)", [$companyId, $outKey, $lowKey]);
    }
}
