<?php
class InventoryController {
    
    // Overview of locations and stock
    public function index(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('stock.view');
        
        // Enforce multi-warehouse feature
        // PlanGuard::enforce('multi_warehouse');

        $tid = Auth::tenantId();
        
        $locations = db()->prepare("SELECT * FROM locations WHERE tenant_id=?");
        $locations->execute([$tid]);
        $locations = $locations->fetchAll();

        // Get total stock valuation per location
        $valuation = [];
        $locStats = db()->prepare(
            "SELECT s.location_id, COUNT(DISTINCT s.product_id) as items_count, SUM(s.quantity * p.cost_price) as total_value
             FROM stock s JOIN products p ON p.id=s.product_id
             WHERE s.tenant_id=? GROUP BY s.location_id"
        );
        $locStats->execute([$tid]);
        foreach ($locStats->fetchAll() as $stat) {
            $valuation[$stat['location_id']] = $stat;
        }

        $pageTitle = 'Inventory & Locations';
        ob_start();
        include APP_ROOT . '/views/tenant/inventory/index.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    // Locations POST
    public function storeLocation(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Security::checkCsrf();
        Auth::requirePermission('settings.view');
        PlanGuard::enforce('locations');

        $data = [
            'tenant_id' => Auth::tenantId(),
            'name'      => Security::sanitize($_POST['name'] ?? ''),
            'code'      => Security::sanitize($_POST['code'] ?? ''),
            'type'      => Security::sanitize($_POST['type'] ?? 'store'),
            'address'   => Security::sanitize($_POST['address'] ?? ''),
        ];

        db()->prepare("INSERT INTO locations (tenant_id,name,code,type,address) VALUES (?,?,?,?,?)")
            ->execute([$data['tenant_id'], $data['name'], $data['code'], $data['type'], $data['address']]);
        
        flash('success', 'Location created successfully');
        redirect('inventory');
    }

    public function adjust(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('stock.adjust');
        $tid = Auth::tenantId();

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            Security::checkCsrf();
            
            // Check if this is a multi-product adjustment (JSON format)
            if (isset($_POST['items'])) {
                header('Content-Type: application/json');
                
                try {
                    $items = json_decode($_POST['items'], true);
                    if (!is_array($items) || empty($items)) {
                        echo json_encode(['success' => false, 'message' => 'Invalid items data']);
                        exit;
                    }
                    
                    $locId = (int)$_POST['location_id'];
                    $referenceNo = Security::sanitize($_POST['reference_no'] ?? '');
                    $adjustmentDate = $_POST['adjustment_date'] ?? date('Y-m-d');
                    
                    if ($locId <= 0) {
                        echo json_encode(['success' => false, 'message' => 'Invalid location']);
                        exit;
                    }
                    
                    db()->beginTransaction();
                    
                    foreach ($items as $item) {
                        $productId = (int)$item['id'];
                        $qty = (float)$item['quantity'];
                        $type = $item['type'] ?? 'add';
                        
                        if ($qty <= 0) continue;
                        
                        $currentStock = 0;
                        $stmt = db()->prepare("SELECT quantity FROM stock WHERE product_id=? AND location_id=? AND tenant_id=? FOR UPDATE");
                        $stmt->execute([$productId, $locId, $tid]);
                        if ($row = $stmt->fetch()) {
                            $currentStock = (float)$row['quantity'];
                        }

                        $diff = 0;
                        if ($type === 'add') {
                            $diff = $qty;
                        } elseif ($type === 'subtract') {
                            $diff = -$qty;
                        } elseif ($type === 'set') {
                            $diff = $qty - $currentStock;
                        }

                        if ($diff != 0) {
                            adjustStock($productId, $locId, $diff, null, $tid);
                            $reason = "Adjustment Ref: {$referenceNo} | Date: {$adjustmentDate} | Type: {$type}";
                            logMovement($productId, $locId, 'adjustment', $diff, $referenceNo, $reason);
                            
                            // Also record in stock_adjustments table for complete audit trail
                            $adjustmentType = ($type === 'add') ? 'add' : 'subtract';
                            $reasonCode = 'correction'; // Default reason for manual adjustments
                            db()->prepare(
                                "INSERT INTO stock_adjustments (tenant_id, reference, product_id, location_id, batch_id, adjustment_type, quantity, reason, note, user_id)
                                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
                            )->execute([$tid, $referenceNo, $productId, $locId, null, $adjustmentType, abs($qty), $reasonCode, $reason, Auth::userId()]);
                        }
                    }

                    db()->commit();
                    echo json_encode(['success' => true, 'message' => 'Stock adjusted successfully']);
                    exit;
                } catch (Exception $e) {
                    db()->rollBack();
                    echo json_encode(['success' => false, 'message' => $e->getMessage()]);
                    exit;
                }
            }
            
            // Original single-product format (backward compatibility)
            $productId  = (int)$_POST['product_id'];
            $locId      = (int)$_POST['location_id'];
            $type       = $_POST['type']; // add, subtract, set
            $qty        = (float)$_POST['quantity'];
            $reason     = Security::sanitize($_POST['reason'] ?? '');
            
            if ($qty <= 0) {
                flash('error', 'Quantity must be greater than 0');
                redirectBack();
            }

            try {
                db()->beginTransaction();
                
                $currentStock = 0;
                $stmt = db()->prepare("SELECT quantity FROM stock WHERE product_id=? AND location_id=? AND tenant_id=? FOR UPDATE");
                $stmt->execute([$productId, $locId, $tid]);
                if ($row = $stmt->fetch()) {
                    $currentStock = (float)$row['quantity'];
                }

                $diff = 0;
                if ($type === 'add') {
                    $diff = $qty;
                } elseif ($type === 'subtract') {
                    $diff = -$qty;
                } elseif ($type === 'set') {
                    $diff = $qty - $currentStock;
                }

                if ($diff != 0) {
                    adjustStock($productId, $locId, $diff, null, $tid);
                    logMovement($productId, $locId, 'adjustment', $diff, null, null, $reason);
                    
                    // Also record in stock_adjustments table for complete audit trail
                    $adjustmentType = ($type === 'add') ? 'add' : 'subtract';
                    $reasonCode = 'correction'; // Default reason for manual adjustments
                    db()->prepare(
                        "INSERT INTO stock_adjustments (tenant_id, reference, product_id, location_id, batch_id, adjustment_type, quantity, reason, note, user_id)
                         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
                    )->execute([$tid, 'ADJ-' . time(), $productId, $locId, null, $adjustmentType, abs($qty), $reasonCode, $reason, Auth::userId()]);
                }

                db()->commit();
                flash('success', 'Stock adjusted successfully');
                redirect('inventory');
            } catch (Exception $e) {
                db()->rollBack();
                flash('error', 'Failed to adjust stock');
                redirectBack();
            }
        }

        $locs = db()->prepare("SELECT * FROM locations WHERE tenant_id=?");
        $locs->execute([$tid]);
        $locations = $locs->fetchAll();

        // Products for dropdown - include cost_price for the new design
        $prods = db()->prepare("SELECT id, name, sku, cost_price FROM products WHERE tenant_id=? AND is_active=1");
        $prods->execute([$tid]);
        $products = $prods->fetchAll();

        $pageTitle = 'Stock Adjustment';
        ob_start();
        include APP_ROOT . '/views/tenant/inventory/adjust.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function transfer(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('stock.transfer');
        $tid = Auth::tenantId();
        
        $locs = db()->prepare("SELECT * FROM locations WHERE tenant_id=?");
        $locs->execute([$tid]);
        $locations = $locs->fetchAll();
        
        if (count($locations) < 2) {
            flash('warning', 'You need at least two locations to perform a transfer.');
            redirect('inventory');
        }

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            Security::checkCsrf();
            
            // Check if this is a multi-product transfer (JSON input)
            if (isset($_POST['items'])) {
                header('Content-Type: application/json');
                
                try {
                    $items = json_decode($_POST['items'], true);
                    if (!is_array($items) || empty($items)) {
                        echo json_encode(['success' => false, 'message' => 'Invalid items data']);
                        exit;
                    }
                    
                    $sourceId = (int)$_POST['source_id'];
                    $destId = (int)$_POST['destination_id'];
                    $referenceNo = Security::sanitize($_POST['reference_no'] ?? '');
                    $transferDate = $_POST['transfer_date'] ?? date('Y-m-d');
                    
                    if ($sourceId === $destId) {
                        echo json_encode(['success' => false, 'message' => 'Source and destination must be different']);
                        exit;
                    }
                    
                    db()->beginTransaction();
                    
                    foreach ($items as $item) {
                        $productId = (int)$item['id'];
                        $qty = (float)$item['quantity'];
                        
                        if ($qty <= 0) continue;
                        
                        // Verify source stock
                        $stmt = db()->prepare("SELECT SUM(quantity) as quantity FROM stock WHERE product_id=? AND location_id=? AND tenant_id=? FOR UPDATE");
                        $stmt->execute([$productId, $sourceId, $tid]);
                        $srcStock = $stmt->fetchColumn();
                        
                        if ($srcStock === false || $srcStock < $qty) {
                            throw new Exception("Insufficient stock for product ID {$productId}");
                        }

                        // Capture balances before adjustment
                        $sourceBalance = $srcStock;
                        $destBalance = getStock($productId, $destId, null, $tid);

                        // Adjust source (-)
                        adjustStock($productId, $sourceId, -$qty, null, $tid);
                        // Adjust dest (+)
                        adjustStock($productId, $destId, $qty, null, $tid);

                        // Log movement with captured balances
                        $ref = $referenceNo ?: 'TRF-' . time();
                        $note = "Transfer Ref: {$referenceNo} | Date: {$transferDate}";
                        logMovementWithBalance($productId, $sourceId, 'transfer_out', -$qty, $ref, $note, null, $tid, $sourceBalance);
                        logMovementWithBalance($productId, $destId, 'transfer_in', $qty, $ref, $note, null, $tid, $destBalance);
                    }

                    db()->commit();
                    echo json_encode(['success' => true, 'message' => 'Stock transferred successfully']);
                    exit;
                } catch (Exception $e) {
                    db()->rollBack();
                    echo json_encode(['success' => false, 'message' => $e->getMessage()]);
                    exit;
                }
            }
            
            // Single product transfer (backward compatibility)
            $productId   = (int)$_POST['product_id'];
            $sourceId    = (int)$_POST['source_id'];
            $destId      = (int)$_POST['destination_id'];
            $qty         = (float)$_POST['quantity'];
            $batchId     = !empty($_POST['batch_id']) ? (int)$_POST['batch_id'] : null;
            $notes       = $_POST['notes'] ?? '';
            
            if ($sourceId === $destId) { flash('error', 'Source and destination must be different'); redirectBack(); }
            if ($qty <= 0) { flash('error', 'Quantity must be > 0'); redirectBack(); }

            try {
                db()->beginTransaction();
                
                // Verify source stock (with batch if specified)
                if ($batchId) {
                    $stmt = db()->prepare("SELECT quantity FROM stock WHERE product_id=? AND location_id=? AND batch_id=? AND tenant_id=? FOR UPDATE");
                    $stmt->execute([$productId, $sourceId, $batchId, $tid]);
                } else {
                    $stmt = db()->prepare("SELECT SUM(quantity) as quantity FROM stock WHERE product_id=? AND location_id=? AND tenant_id=? FOR UPDATE");
                    $stmt->execute([$productId, $sourceId, $tid]);
                }
                $srcStock = $stmt->fetchColumn();
                
                if ($srcStock === false || $srcStock < $qty) {
                    throw new Exception("Insufficient stock in source location");
                }

                // Capture balances before adjustment
                $sourceBalance = $srcStock;
                $destBalance = getStock($productId, $destId, $batchId, $tid);

                // Adjust source (-)
                adjustStock($productId, $sourceId, -$qty, $batchId, $tid);
                // Adjust dest (+)
                adjustStock($productId, $destId, $qty, $batchId, $tid);

                // Log movement with captured balances
                $ref = 'TRF-' . time();
                $note = $notes ? $notes : "To location ID {$destId}";
                logMovementWithBalance($productId, $sourceId, 'transfer_out', -$qty, $ref, $note, $batchId, $tid, $sourceBalance);
                $note = $notes ? $notes : "From location ID {$sourceId}";
                logMovementWithBalance($productId, $destId, 'transfer_in', $qty, $ref, $note, $batchId, $tid, $destBalance);

                db()->commit();
                flash('success', 'Stock transferred successfully');
                redirect('inventory');
            } catch (Exception $e) {
                db()->rollBack();
                flash('error', $e->getMessage());
                redirectBack();
            }
        }

        $prods = db()->prepare("SELECT id, name, sku, batch_tracking FROM products WHERE tenant_id=? AND is_active=1");
        $prods->execute([$tid]);
        $products = $prods->fetchAll();

        $pageTitle = 'Transfer Stock';
        ob_start();
        include APP_ROOT . '/views/tenant/inventory/transfer.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function history(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('stock.view');
        $tid = Auth::tenantId();

        $page = (int)($_GET['page'] ?? 1) ?: 1;
        $perPage = $_GET['per_page'] ?? ITEMS_PER_PAGE;
        $pp = $perPage === 'all' ? PHP_INT_MAX : (int)$perPage;
        $offset = ($page-1)*$pp;

        $where = "sm.tenant_id = :tid";
        $params = [':tid' => $tid];

        if (!empty($_GET['product_id'])) {
            $where .= " AND sm.product_id = :pid";
            $params[':pid'] = $_GET['product_id'];
        }
        if (!empty($_GET['location_id'])) {
            $where .= " AND sm.location_id = :lid";
            $params[':lid'] = $_GET['location_id'];
        }
        if (!empty($_GET['type'])) {
            $where .= " AND sm.type = :type";
            $params[':type'] = $_GET['type'];
        }

        $cntStmt = db()->prepare("SELECT COUNT(*) FROM stock_movements sm WHERE {$where}");
        $cntStmt->execute($params);
        $total = (int)$cntStmt->fetchColumn();

        $sql = "SELECT sm.*, p.name as product_name, p.sku, l.name as location_name, u.name as user_name
                FROM stock_movements sm
                JOIN products p ON p.id = sm.product_id
                JOIN locations l ON l.id = sm.location_id
                LEFT JOIN users u ON u.id = sm.user_id
                WHERE {$where} ORDER BY sm.created_at DESC LIMIT {$pp} OFFSET {$offset}";
        $stmt = db()->prepare($sql);
        $stmt->execute($params);
        
        $movements = [
            'data' => $stmt->fetchAll(),
            'total' => $total,
            'last_page' => $perPage === 'all' ? 1 : (int)ceil($total/$pp),
            'page' => $page
        ];

        $pageTitle = 'Stock Movement History';
        ob_start();
        include APP_ROOT . '/views/tenant/inventory/history.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function adjustmentList(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('stock.view');
        $tid = Auth::tenantId();

        $page = (int)($_GET['page'] ?? 1) ?: 1;
        $perPage = $_GET['per_page'] ?? ITEMS_PER_PAGE;
        $pp = $perPage === 'all' ? PHP_INT_MAX : (int)$perPage;
        $offset = ($page-1)*$pp;

        $where = "sa.tenant_id = :tid";
        $params = [':tid' => $tid];

        if (!empty($_GET['product_id'])) {
            $where .= " AND sa.product_id = :pid";
            $params[':pid'] = $_GET['product_id'];
        }
        if (!empty($_GET['location_id'])) {
            $where .= " AND sa.location_id = :lid";
            $params[':lid'] = $_GET['location_id'];
        }
        if (!empty($_GET['adjustment_type'])) {
            $where .= " AND sa.adjustment_type = :adjustment_type";
            $params[':adjustment_type'] = $_GET['adjustment_type'];
        }
        if (!empty($_GET['date_from'])) {
            $where .= " AND DATE(sa.created_at) >= :date_from";
            $params[':date_from'] = $_GET['date_from'];
        }
        if (!empty($_GET['date_to'])) {
            $where .= " AND DATE(sa.created_at) <= :date_to";
            $params[':date_to'] = $_GET['date_to'];
        }

        $cntStmt = db()->prepare("SELECT COUNT(*) FROM stock_adjustments sa WHERE {$where}");
        $cntStmt->execute($params);
        $total = (int)$cntStmt->fetchColumn();

        $sql = "SELECT sa.*, p.name as product_name, p.sku, l.name as location_name, u.name as user_name
                FROM stock_adjustments sa
                JOIN products p ON p.id = sa.product_id
                JOIN locations l ON l.id = sa.location_id
                LEFT JOIN users u ON u.id = sa.user_id
                WHERE {$where} ORDER BY sa.created_at DESC LIMIT {$pp} OFFSET {$offset}";
        $stmt = db()->prepare($sql);
        $stmt->execute($params);
        
        $adjustments = [
            'data' => $stmt->fetchAll(),
            'total' => $total,
            'last_page' => $perPage === 'all' ? 1 : (int)ceil($total/$pp),
            'page' => $page
        ];

        // Get filter options
        $locs = db()->prepare("SELECT * FROM locations WHERE tenant_id=?");
        $locs->execute([$tid]);
        $locations = $locs->fetchAll();

        $prods = db()->prepare("SELECT id, name, sku FROM products WHERE tenant_id=? AND is_active=1");
        $prods->execute([$tid]);
        $products = $prods->fetchAll();

        $pageTitle = 'Stock Adjustment List';
        ob_start();
        include APP_ROOT . '/views/tenant/inventory/adjustment-list.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function reconcile(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('stock.adjust');

        $tid = Auth::tenantId();

        // Find products with discrepancies
        $stmt = db()->prepare("
            SELECT p.id, p.name, p.sku,
                   COALESCE(SUM(s.quantity), 0) as stock_qty,
                   (
                       SELECT COALESCE(SUM(CASE 
                           WHEN sm.type IN ('purchase', 'transfer_in', 'adjustment_in') OR (sm.type IN ('adjustment', 'return') AND sm.quantity > 0) THEN ABS(sm.quantity)
                           ELSE 0
                       END), 0) - 
                       COALESCE(SUM(CASE 
                           WHEN sm.type IN ('sale', 'transfer_out', 'adjustment_out') OR (sm.type IN ('adjustment', 'return') AND sm.quantity < 0) THEN ABS(sm.quantity)
                           ELSE 0
                       END), 0)
                       FROM stock_movements sm
                       WHERE sm.product_id = p.id AND sm.tenant_id = p.tenant_id
                   ) as movement_qty
            FROM products p
            LEFT JOIN stock s ON s.product_id = p.id AND s.tenant_id = p.tenant_id
            WHERE p.tenant_id = ? AND p.is_active = 1
            GROUP BY p.id
            HAVING ABS(stock_qty - movement_qty) > 0.01
            ORDER BY p.name
        ");
        $stmt->execute([$tid]);
        $discrepancies = $stmt->fetchAll();

        $pageTitle = 'Stock Reconciliation';
        ob_start();
        include APP_ROOT . '/views/tenant/inventory/reconcile.php';
        $content = ob_get_clean();
        include APP_ROOT . '/views/tenant/layouts/main.php';
    }

    public function reconcileFix(): void {
        Auth::requireLogin();
        Auth::requireActiveTenant();
        Auth::requirePermission('stock.adjust');
        Security::checkCsrf();

        $tid = Auth::tenantId();

        // Find products with discrepancies
        $stmt = db()->prepare("
            SELECT p.id, p.name, p.sku,
                   COALESCE(SUM(s.quantity), 0) as stock_qty,
                   (
                       SELECT COALESCE(SUM(CASE 
                           WHEN sm.type IN ('purchase', 'transfer_in', 'adjustment_in') OR (sm.type IN ('adjustment', 'return') AND sm.quantity > 0) THEN ABS(sm.quantity)
                           ELSE 0
                       END), 0) - 
                       COALESCE(SUM(CASE 
                           WHEN sm.type IN ('sale', 'transfer_out', 'adjustment_out') OR (sm.type IN ('adjustment', 'return') AND sm.quantity < 0) THEN ABS(sm.quantity)
                           ELSE 0
                       END), 0)
                       FROM stock_movements sm
                       WHERE sm.product_id = p.id AND sm.tenant_id = p.tenant_id
                   ) as movement_qty
            FROM products p
            LEFT JOIN stock s ON s.product_id = p.id AND s.tenant_id = p.tenant_id
            WHERE p.tenant_id = ? AND p.is_active = 1
            GROUP BY p.id
            HAVING ABS(stock_qty - movement_qty) > 0.01
            ORDER BY p.name
        ");
        $stmt->execute([$tid]);
        $discrepancies = $stmt->fetchAll();

        $fixed = 0;
        $errors = [];

        foreach ($discrepancies as $d) {
            $movementQty = $d['movement_qty'];
            $productId = $d['id'];

            // Get all stock records for this product
            $stockStmt = db()->prepare("SELECT id, location_id, quantity FROM stock WHERE product_id = ? AND tenant_id = ?");
            $stockStmt->execute([$productId, $tid]);
            $stockRecords = $stockStmt->fetchAll();

            if (empty($stockRecords)) {
                // No stock records, create one if movement_qty > 0
                if ($movementQty > 0) {
                    $locStmt = db()->prepare("SELECT id FROM locations WHERE tenant_id = ? AND is_default = 1 LIMIT 1");
                    $locStmt->execute([$tid]);
                    $location = $locStmt->fetch();

                    if ($location) {
                        $insertStmt = db()->prepare("INSERT INTO stock (tenant_id, product_id, location_id, quantity) VALUES (?, ?, ?, ?)");
                        try {
                            $insertStmt->execute([$tid, $productId, $location['id'], $movementQty]);
                            $fixed++;
                        } catch (Exception $e) {
                            $errors[] = "Failed to create stock for {$d['name']}: " . $e->getMessage();
                        }
                    } else {
                        $errors[] = "No default location found for {$d['name']}";
                    }
                }
            } elseif (count($stockRecords) === 1) {
                // Single stock record, update it
                $updateStmt = db()->prepare("UPDATE stock SET quantity = ? WHERE id = ? AND tenant_id = ?");
                try {
                    $updateStmt->execute([$movementQty, $stockRecords[0]['id'], $tid]);
                    $fixed++;
                } catch (Exception $e) {
                    $errors[] = "Failed to update stock for {$d['name']}: " . $e->getMessage();
                }
            } else {
                // Multiple stock records (different locations/batches)
                // Update the first one and set others to 0
                $totalUpdated = 0;
                foreach ($stockRecords as $index => $record) {
                    if ($index === 0) {
                        // First record gets the full movement quantity
                        $updateStmt = db()->prepare("UPDATE stock SET quantity = ? WHERE id = ? AND tenant_id = ?");
                        try {
                            $updateStmt->execute([$movementQty, $record['id'], $tid]);
                            $totalUpdated++;
                        } catch (Exception $e) {
                            $errors[] = "Failed to update stock for {$d['name']}: " . $e->getMessage();
                        }
                    } else {
                        // Set other records to 0
                        $updateStmt = db()->prepare("UPDATE stock SET quantity = 0 WHERE id = ? AND tenant_id = ?");
                        try {
                            $updateStmt->execute([$record['id'], $tid]);
                            $totalUpdated++;
                        } catch (Exception $e) {
                            $errors[] = "Failed to zero stock for {$d['name']}: " . $e->getMessage();
                        }
                    }
                }
                if ($totalUpdated > 0) {
                    $fixed++;
                }
            }
        }

        if (!empty($errors)) {
            flash('error', "Fixed $fixed products with errors: " . implode('; ', $errors));
        } else {
            flash('success', "Fixed $fixed products. Stock table now matches movement history.");
        }
        redirect('inventory/reconcile');
    }
}
