<?php
// Catch ALL errors including fatal ones
set_error_handler(function ($errno, $errstr) {
    if (!(error_reporting() & $errno))
        return false;
    header('Content-Type: application/json; charset=utf-8');
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => "PHP Error: $errstr", 'data' => null, 'errors' => []]);
    exit;
});
register_shutdown_function(function () {
    $e = error_get_last();
    if ($e && in_array($e['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        if (!headers_sent()) {
            header('Content-Type: application/json; charset=utf-8');
            http_response_code(500);
        }
        echo json_encode(['success' => false, 'message' => 'Fatal: ' . $e['message'] . ' in ' . $e['file'] . ' line ' . $e['line'], 'data' => null, 'errors' => []]);
    }
});

require_once __DIR__ . '/../config/db.php';
require_once __DIR__ . '/../config/auth.php';
$user = requireAuth();
$db = getDB();
$action = post('action', 'list');

try {
    // Check which optional columns exist
    static $cols = null;
    if ($cols === null) {
        try {
            $colStmt = $db->query("SHOW COLUMNS FROM stock_items");
            $cols = array_column($colStmt->fetchAll(), 'Field');
        } catch (Exception $e) {
            $cols = [];
        }
    }
    $hasImagePath = in_array('image_path', $cols);

    $imageSelect = $hasImagePath ? "COALESCE(si.image_path, '') AS image_path," : "'' AS image_path,";

    if ($action === 'list') {
        $p = getPagination();
        $search = post('search', '');
        $catId = post('category_id', '');
        $lowStock = (int) post('low_stock', 0);
        $zeroCost = (int) post('zero_cost', 0);
        $noImage = (int) post('no_image', 0);

        $where = ['si.is_active = 1'];
        $params = [];

        if ($search !== '' && $search !== null) {
            $where[] = '(si.name LIKE ? OR si.sku LIKE ?)';
            $params[] = "%$search%";
            $params[] = "%$search%";
        }
        if ($catId !== '' && $catId !== null) {
            $where[] = 'si.category_id = ?';
            $params[] = (int) $catId;
        }
        if ($lowStock) {
            $where[] = 'COALESCE(inv_sum.total_qty, 0) <= si.min_qty';
        }
        if ($zeroCost) {
            $where[] = '(si.unit_cost IS NULL OR si.unit_cost = 0)';
        }
        if ($noImage && $hasImagePath) {
            $where[] = '(si.image_path IS NULL OR si.image_path = \'\')';
        }
        $ws = implode(' AND ', $where);

        // Count
        $cntStmt = $db->prepare("
            SELECT COUNT(*) FROM stock_items si
            LEFT JOIN (
                SELECT stock_item_id, SUM(quantity) AS total_qty
                FROM stock_inventory GROUP BY stock_item_id
            ) inv_sum ON inv_sum.stock_item_id = si.id
            WHERE $ws
        ");
        $cntStmt->execute($params);
        $total = (int) $cntStmt->fetchColumn();

        // Items
        $stmt = $db->prepare("
            SELECT si.id, si.sku, si.name, si.description, si.category_id,
                   si.item_type, si.unit, si.unit_cost, si.min_qty, si.max_qty, si.is_active,
                   $imageSelect
                   sc.name AS category_name,
                   COALESCE(inv_sum.total_qty, 0) AS qty_on_hand,
                   ROUND(COALESCE(inv_sum.total_qty, 0) * COALESCE(si.unit_cost, 0), 2) AS stock_value
            FROM stock_items si
            LEFT JOIN stock_categories sc ON sc.id = si.category_id
            LEFT JOIN (
                SELECT stock_item_id, SUM(quantity) AS total_qty
                FROM stock_inventory GROUP BY stock_item_id
            ) inv_sum ON inv_sum.stock_item_id = si.id
            WHERE $ws
            ORDER BY si.name ASC
            LIMIT {$p['limit']} OFFSET {$p['offset']}
        ");
        $stmt->execute($params);
        $items = $stmt->fetchAll();

        apiSuccess([
            'items' => $items,
            'pagination' => [
                'total' => $total,
                'page' => $p['page'],
                'limit' => $p['limit'],
                'pages' => $total > 0 ? (int) ceil($total / $p['limit']) : 1,
            ]
        ]);
    }

    if ($action === 'get') {
        $id = (int) post('id');
        $stmt = $db->prepare("
            SELECT si.*, sc.name AS category_name,
                   $imageSelect
                   COALESCE(inv_sum.total_qty, 0) AS qty_on_hand
            FROM stock_items si
            LEFT JOIN stock_categories sc ON sc.id = si.category_id
            LEFT JOIN (
                SELECT stock_item_id, SUM(quantity) AS total_qty
                FROM stock_inventory GROUP BY stock_item_id
            ) inv_sum ON inv_sum.stock_item_id = si.id
            WHERE si.id = ?
        ");
        $stmt->execute([$id]);
        $item = $stmt->fetch();
        if (!$item)
            apiError('Item not found.', 404);
        apiSuccess(['item' => $item]);
    }

    if ($action === 'search') {
        $q = post('q', '');
        $stmt = $db->prepare("
            SELECT si.id, si.name, si.sku, si.unit, si.unit_cost, sc.name AS category_name,
                   COALESCE(inv_sum.total_qty, 0) AS qty_on_hand
            FROM stock_items si
            LEFT JOIN stock_categories sc ON sc.id = si.category_id
            LEFT JOIN (
                SELECT stock_item_id, SUM(quantity) AS total_qty
                FROM stock_inventory GROUP BY stock_item_id
            ) inv_sum ON inv_sum.stock_item_id = si.id
            WHERE si.is_active = 1 AND (si.name LIKE ? OR si.sku LIKE ?)
            ORDER BY si.name LIMIT 15
        ");
        $stmt->execute(["%$q%", "%$q%"]);
        apiSuccess(['items' => $stmt->fetchAll()]);
    }

    // Write actions
    requireRole([1, 2, 4, 5]);

    if ($action === 'save') {
        $id = (int) post('id', 0);
        $name = trim(post('name', ''));
        if (!$name)
            apiError('Item name required.', 422);

        // Check unique name
        $dupStmt = $db->prepare("SELECT id FROM stock_items WHERE name = ? AND id != ?");
        $dupStmt->execute([$name, $id]);
        if ($dupStmt->fetch())
            apiError("An item named '$name' already exists.", 409);

        $sku = trim(post('sku', ''));
        if (!$sku)
            $sku = strtoupper(preg_replace('/[^A-Z0-9]/', '', strtoupper($name)));
        if (!$sku)
            $sku = 'ITEM';
        $sku = substr($sku, 0, 20) . '-' . rand(100, 999);

        $supplier = trim(post('supplier', ''));
        $catId = post('category_id') ?: null;
        $itemType = post('item_type', 'consumable');
        $unit = post('unit', 'each');
        $unitCost = (post('unit_cost') !== null && post('unit_cost') !== '') ? (float) post('unit_cost') : null;
        $minQty = (float) post('min_qty', 0);
        $maxQty = (post('max_qty') !== null && post('max_qty') !== '') ? (float) post('max_qty') : null;
        $desc = post('description', '');

        if ($id) {
            $db->prepare("
                UPDATE stock_items
                SET name=?, sku=?, description=?, supplier=?, category_id=?, item_type=?,
                    unit=?, unit_cost=?, min_qty=?, max_qty=?
                WHERE id=?
            ")->execute([$name, $sku, $desc, $supplier, $catId, $itemType, $unit, $unitCost, $minQty, $maxQty, $id]);
            apiSuccess(['id' => $id], 'Item updated.');
        } else {
            $db->prepare("
                INSERT INTO stock_items (name, sku, description, supplier, category_id, item_type, unit, unit_cost, min_qty, max_qty, is_active)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
            ")->execute([$name, $sku, $desc, $supplier, $catId, $itemType, $unit, $unitCost, $minQty, $maxQty]);
            $newId = (int) $db->lastInsertId();

            // Get or create default location for inventory entry
            $loc = $db->query("SELECT id FROM stock_locations WHERE is_active=1 ORDER BY id LIMIT 1")->fetch();
            if (!$loc) {
                $db->exec("INSERT INTO stock_locations (name) VALUES ('Main Warehouse')");
                $locId = (int) $db->lastInsertId();
            } else {
                $locId = (int) $loc['id'];
            }
            $db->prepare("INSERT IGNORE INTO stock_inventory (stock_item_id, location_id, quantity) VALUES (?,?,0)")
                ->execute([$newId, $locId]);

            apiSuccess(['id' => $newId], 'Item created.');
        }
    }

    if ($action === 'delete') {
        $db->prepare("UPDATE stock_items SET is_active=0 WHERE id=?")->execute([(int) post('id')]);
        apiSuccess([], 'Item deactivated.');
    }

    if ($action === 'remove_image') {
        $id = (int) post('id', 0);
        if (!$id)
            apiError('ID required.', 422);
        $row = $db->prepare("SELECT image_path FROM stock_items WHERE id=?");
        $row->execute([$id]);
        $item = $row->fetch();
        if ($item && $item['image_path']) {
            $abs = __DIR__ . '/../../' . $item['image_path'];
            if (file_exists($abs))
                @unlink($abs);
        }
        $db->prepare("UPDATE stock_items SET image_path=NULL WHERE id=?")->execute([$id]);
        apiSuccess([], 'Image removed.');
    }

    apiError('Unknown action: ' . $action, 400);

} catch (PDOException $e) {
    apiError('Database error: ' . $e->getMessage(), 500);
} catch (Exception $e) {
    apiError('Error: ' . $e->getMessage(), 500);
}