<?php
if (!function_exists('nay_stock_table_exists')) {
    function nay_stock_table_exists(mysqli $conn, string $table): bool
    {
        $table = trim($table);
        if ($table === '') {
            return false;
        }
        $escaped = $conn->real_escape_string($table);
        $res = $conn->query("SHOW TABLES LIKE '{$escaped}'");
        return $res instanceof mysqli_result && $res->num_rows > 0;
    }
}

if (!function_exists('nay_stock_column_exists')) {
    function nay_stock_column_exists(mysqli $conn, string $table, string $column): bool
    {
        if (!nay_stock_table_exists($conn, $table) || $column === '') {
            return false;
        }
        $tableEsc = $conn->real_escape_string($table);
        $colEsc = $conn->real_escape_string($column);
        $res = $conn->query("SHOW COLUMNS FROM `{$tableEsc}` LIKE '{$colEsc}'");
        return $res instanceof mysqli_result && $res->num_rows > 0;
    }
}

if (!function_exists('nay_stock_settings')) {
    function nay_stock_settings(mysqli $conn): array
    {
        static $cache = null;
        if (is_array($cache)) {
            return $cache;
        }
        $cache = [];
        if (!nay_stock_table_exists($conn, 'settings')) {
            return $cache;
        }
        if ($res = $conn->query("SELECT setting_key, setting_value FROM settings")) {
            while ($row = $res->fetch_assoc()) {
                $cache[(string)($row['setting_key'] ?? '')] = (string)($row['setting_value'] ?? '');
            }
            $res->close();
        }
        return $cache;
    }
}

if (!function_exists('nay_stock_setting')) {
    function nay_stock_setting(mysqli $conn, string $key, $default = '')
    {
        $settings = nay_stock_settings($conn);
        return array_key_exists($key, $settings) ? $settings[$key] : $default;
    }
}

if (!function_exists('nay_stock_default_threshold')) {
    function nay_stock_default_threshold(mysqli $conn): int
    {
        return max(0, (int)nay_stock_setting($conn, 'inventory_low_stock_threshold', '5'));
    }
}

if (!function_exists('nay_stock_alert_enabled')) {
    function nay_stock_alert_enabled(mysqli $conn): bool
    {
        return (string)nay_stock_setting($conn, 'inventory_low_stock_alert_enabled', '1') !== '0';
    }
}

if (!function_exists('nay_stock_allow_backorder')) {
    function nay_stock_allow_backorder(mysqli $conn): bool
    {
        return (string)nay_stock_setting($conn, 'inventory_allow_backorder', '0') === '1';
    }
}

if (!function_exists('nay_stock_effective_threshold')) {
    function nay_stock_effective_threshold(mysqli $conn, $rowThreshold): int
    {
        $specific = max(0, (int)$rowThreshold);
        return $specific > 0 ? $specific : nay_stock_default_threshold($conn);
    }
}

if (!function_exists('nay_stock_state')) {
    function nay_stock_state(mysqli $conn, int $qty, int $threshold): string
    {
        if ($qty <= 0) {
            return 'zero';
        }
        if (nay_stock_alert_enabled($conn) && $qty <= max(0, $threshold)) {
            return 'low';
        }
        return 'healthy';
    }
}

if (!function_exists('nay_stock_badge_meta')) {
    function nay_stock_badge_meta(string $state): array
    {
        switch ($state) {
            case 'zero':
                return ['label' => 'نافد', 'class' => 'red'];
            case 'low':
                return ['label' => 'منخفض', 'class' => 'orange'];
            default:
                return ['label' => 'جيد', 'class' => 'green'];
        }
    }
}

if (!function_exists('nay_stock_resolve_image')) {
    function nay_stock_resolve_image(?string $raw): ?string
    {
        $raw = trim((string)$raw);
        if ($raw === '') {
            return null;
        }
        if (preg_match('~^https?://~i', $raw)) {
            return $raw;
        }
        $raw = ltrim(str_replace('\\', '/', $raw), '/');
        if (strpos($raw, 'app/admin/uploads/products/') === 0) {
            return '../' . $raw;
        }
        if (strpos($raw, 'uploads/products/') === 0) {
            return '../' . $raw;
        }
        if (strpos($raw, 'products/') === 0) {
            return '../uploads/' . $raw;
        }
        return '../uploads/products/' . $raw;
    }
}

if (!function_exists('nay_stock_sync_parent_from_variants')) {
    function nay_stock_sync_parent_from_variants(mysqli $conn, int $productId): void
    {
        if ($productId <= 0 || !nay_stock_table_exists($conn, 'product_variants')) {
            return;
        }
        $sum = 0;
        $stmt = $conn->prepare("SELECT COALESCE(SUM(stock_qty),0) AS total FROM product_variants WHERE product_id = ? AND status = 1");
        $stmt->bind_param('i', $productId);
        $stmt->execute();
        $sum = (int)(($stmt->get_result()->fetch_assoc()['total'] ?? 0));
        $stmt->close();

        if (nay_stock_column_exists($conn, 'products', 'updated_at')) {
            $stmt = $conn->prepare("UPDATE products SET stock_qty = ?, updated_at = NOW() WHERE id = ?");
        } else {
            $stmt = $conn->prepare("UPDATE products SET stock_qty = ? WHERE id = ?");
        }
        $stmt->bind_param('ii', $sum, $productId);
        $stmt->execute();
        $stmt->close();
    }
}

if (!function_exists('nay_stock_fetch_target')) {
    function nay_stock_fetch_target(mysqli $conn, string $target, int $id): ?array
    {
        if ($id <= 0) {
            return null;
        }

        if ($target === 'variant') {
            $sql = "SELECT pv.id, pv.product_id, pv.variant_name AS name, pv.sku, pv.stock_qty, pv.low_stock_alert,
                           pv.variant_image AS image, pv.status, p.name AS parent_name, p.has_variants
                    FROM product_variants pv
                    INNER JOIN products p ON p.id = pv.product_id
                    WHERE pv.id = ?
                    LIMIT 1";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param('i', $id);
            $stmt->execute();
            $row = $stmt->get_result()->fetch_assoc();
            $stmt->close();
            if (!$row) {
                return null;
            }
            $row['target_type'] = 'variant';
            $row['display_name'] = trim((string)$row['parent_name'] . ' - ' . (string)$row['name']);
            $row['managed_by'] = 'variant';
            $row['effective_threshold'] = nay_stock_effective_threshold($conn, $row['low_stock_alert'] ?? 0);
            $row['state'] = nay_stock_state($conn, (int)$row['stock_qty'], (int)$row['effective_threshold']);
            return $row;
        }

        $sql = "SELECT p.id, p.name, p.sku, p.stock_qty, p.low_stock_alert, p.main_image AS image, p.status, p.has_variants,
                       (SELECT COALESCE(SUM(pv.stock_qty),0) FROM product_variants pv WHERE pv.product_id = p.id AND pv.status = 1) AS variants_stock_total,
                       (SELECT COUNT(*) FROM product_variants pv WHERE pv.product_id = p.id AND pv.status = 1) AS variants_count
                FROM products p
                WHERE p.id = ?
                LIMIT 1";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param('i', $id);
        $stmt->execute();
        $row = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        if (!$row) {
            return null;
        }
        $row['product_id'] = (int)$row['id'];
        $row['variant_id'] = null;
        $row['parent_name'] = null;
        $row['target_type'] = 'product';
        $row['display_name'] = (string)$row['name'];
        $row['managed_by'] = (int)$row['has_variants'] === 1 ? 'variants' : 'product';
        $row['effective_threshold'] = nay_stock_effective_threshold($conn, $row['low_stock_alert'] ?? 0);
        $visibleQty = $row['managed_by'] === 'variants' ? (int)$row['variants_stock_total'] : (int)$row['stock_qty'];
        $row['visible_stock_qty'] = $visibleQty;
        $row['state'] = nay_stock_state($conn, $visibleQty, (int)$row['effective_threshold']);
        return $row;
    }
}

if (!function_exists('nay_stock_write_log')) {
    function nay_stock_write_log(mysqli $conn, array $payload): void
    {
        if (!nay_stock_table_exists($conn, 'inventory_movements')) {
            return;
        }
        $sql = "INSERT INTO inventory_movements (
                    target_type, product_id, variant_id, admin_id, source, action_type, reason_code,
                    reference_type, reference_id, qty_before, qty_change, qty_after, notes, created_at
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())";
        $stmt = $conn->prepare($sql);
        $targetType = (string)($payload['target_type'] ?? 'product');
        $productId = !empty($payload['product_id']) ? (int)$payload['product_id'] : null;
        $variantId = !empty($payload['variant_id']) ? (int)$payload['variant_id'] : null;
        $adminId = !empty($payload['admin_id']) ? (int)$payload['admin_id'] : null;
        $source = (string)($payload['source'] ?? 'admin_manual');
        $actionType = (string)($payload['action_type'] ?? 'set');
        $reasonCode = trim((string)($payload['reason_code'] ?? 'manual_adjustment')) ?: 'manual_adjustment';
        $referenceType = trim((string)($payload['reference_type'] ?? '')) ?: null;
        $referenceId = isset($payload['reference_id']) && $payload['reference_id'] !== '' ? (int)$payload['reference_id'] : null;
        $qtyBefore = (int)($payload['qty_before'] ?? 0);
        $qtyChange = (int)($payload['qty_change'] ?? 0);
        $qtyAfter = (int)($payload['qty_after'] ?? 0);
        $notes = trim((string)($payload['notes'] ?? '')) ?: null;
        $stmt->bind_param('siiissssiiiss', $targetType, $productId, $variantId, $adminId, $source, $actionType, $reasonCode, $referenceType, $referenceId, $qtyBefore, $qtyChange, $qtyAfter, $notes);
        $stmt->execute();
        $stmt->close();
    }
}

if (!function_exists('nay_stock_apply_change')) {
    function nay_stock_apply_change(mysqli $conn, string $target, int $id, string $mode, int $qty, array $meta = []): array
    {
        $row = nay_stock_fetch_target($conn, $target, $id);
        if (!$row) {
            throw new RuntimeException('العنصر المطلوب غير موجود.');
        }
        if ($target === 'product' && ($row['managed_by'] ?? '') === 'variants') {
            throw new RuntimeException('هذا المنتج يعتمد على الفاريانتات. عدّل المخزون من الفاريانتات نفسها.');
        }

        $before = (int)($row['stock_qty'] ?? 0);
        $after = $before;
        $change = 0;
        switch ($mode) {
            case 'set':
                if ($qty < 0) {
                    throw new RuntimeException('القيمة غير صالحة.');
                }
                $after = $qty;
                $change = $after - $before;
                break;
            case 'add':
            case 'restore':
                if ($qty <= 0) {
                    throw new RuntimeException('الكمية يجب أن تكون أكبر من صفر.');
                }
                $after = $before + $qty;
                $change = $qty;
                break;
            case 'deduct':
                if ($qty <= 0) {
                    throw new RuntimeException('الكمية يجب أن تكون أكبر من صفر.');
                }
                if (!nay_stock_allow_backorder($conn) && $qty > $before) {
                    throw new RuntimeException('الكمية المطلوبة أكبر من المخزون المتوفر.');
                }
                $after = max(0, $before - $qty);
                $change = -1 * min($qty, $before);
                break;
            case 'zero':
                $after = 0;
                $change = -1 * $before;
                break;
            default:
                throw new RuntimeException('إجراء المخزون غير معروف.');
        }

        if ($target === 'variant') {
            if (nay_stock_column_exists($conn, 'product_variants', 'updated_at')) {
                $stmt = $conn->prepare("UPDATE product_variants SET stock_qty = ?, updated_at = NOW() WHERE id = ?");
            } else {
                $stmt = $conn->prepare("UPDATE product_variants SET stock_qty = ? WHERE id = ?");
            }
            $stmt->bind_param('ii', $after, $id);
            $stmt->execute();
            $stmt->close();
            nay_stock_sync_parent_from_variants($conn, (int)$row['product_id']);
        } else {
            if (nay_stock_column_exists($conn, 'products', 'updated_at')) {
                $stmt = $conn->prepare("UPDATE products SET stock_qty = ?, updated_at = NOW() WHERE id = ?");
            } else {
                $stmt = $conn->prepare("UPDATE products SET stock_qty = ? WHERE id = ?");
            }
            $stmt->bind_param('ii', $after, $id);
            $stmt->execute();
            $stmt->close();
        }

        nay_stock_write_log($conn, [
            'target_type' => $target,
            'product_id' => (int)($row['product_id'] ?? $row['id'] ?? 0),
            'variant_id' => $target === 'variant' ? (int)$id : null,
            'admin_id' => isset($meta['admin_id']) ? (int)$meta['admin_id'] : (function_exists('current_admin_id') ? current_admin_id() : null),
            'source' => (string)($meta['source'] ?? 'admin_manual'),
            'action_type' => $mode,
            'reason_code' => (string)($meta['reason_code'] ?? ($mode === 'deduct' ? 'order_deduction' : 'manual_adjustment')),
            'reference_type' => (string)($meta['reference_type'] ?? ''),
            'reference_id' => $meta['reference_id'] ?? null,
            'qty_before' => $before,
            'qty_change' => $change,
            'qty_after' => $after,
            'notes' => (string)($meta['notes'] ?? ''),
        ]);

        return [
            'before' => $before,
            'after' => $after,
            'change' => $change,
            'row' => $row,
        ];
    }
}

if (!function_exists('nay_stock_update_meta')) {
    function nay_stock_update_meta(mysqli $conn, string $target, int $id, array $fields): void
    {
        $allowed = [
            'low_stock_alert' => 'i',
            'status' => 'i',
        ];
        $sets = [];
        $types = '';
        $values = [];
        foreach ($fields as $column => $value) {
            if (!array_key_exists($column, $allowed)) {
                continue;
            }
            $sets[] = "{$column} = ?";
            $types .= $allowed[$column];
            $values[] = (int)$value;
        }
        if (!$sets) {
            return;
        }
        $table = $target === 'variant' ? 'product_variants' : 'products';
        if (nay_stock_column_exists($conn, $table, 'updated_at')) {
            $sets[] = 'updated_at = NOW()';
        }
        $types .= 'i';
        $values[] = $id;
        $sql = "UPDATE {$table} SET " . implode(', ', $sets) . " WHERE id = ?";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param($types, ...$values);
        $stmt->execute();
        $stmt->close();
        if ($target === 'variant') {
            $targetRow = nay_stock_fetch_target($conn, 'variant', $id);
            if ($targetRow && !empty($targetRow['product_id'])) {
                nay_stock_sync_parent_from_variants($conn, (int)$targetRow['product_id']);
            }
        }
    }
}

if (!function_exists('nay_stock_reason_labels')) {
    function nay_stock_reason_labels(): array
    {
        return [
            'manual_adjustment' => 'تعديل يدوي',
            'stock_count' => 'جرد مخزني',
            'purchase' => 'توريد / شراء',
            'damage' => 'تالف / كسر',
            'correction' => 'تصحيح',
            'order_deduction' => 'خصم بسبب طلب',
            'order_restore' => 'إرجاع بسبب إلغاء طلب',
        ];
    }
}

if (!function_exists('nay_stock_fetch_movements')) {
    function nay_stock_fetch_movements(mysqli $conn, array $filters = []): array
    {
        if (!nay_stock_table_exists($conn, 'inventory_movements')) {
            return [];
        }
        $limit = max(1, min(250, (int)($filters['limit'] ?? 50)));
        $where = [];
        $params = [];
        $types = '';

        if (!empty($filters['product_id'])) {
            $where[] = 'im.product_id = ?';
            $params[] = (int)$filters['product_id'];
            $types .= 'i';
        }
        if (!empty($filters['variant_id'])) {
            $where[] = 'im.variant_id = ?';
            $params[] = (int)$filters['variant_id'];
            $types .= 'i';
        }
        if (!empty($filters['target_type'])) {
            $where[] = 'im.target_type = ?';
            $params[] = (string)$filters['target_type'];
            $types .= 's';
        }
        if (!empty($filters['source'])) {
            $where[] = 'im.source = ?';
            $params[] = (string)$filters['source'];
            $types .= 's';
        }
        if (!empty($filters['action_type'])) {
            $where[] = 'im.action_type = ?';
            $params[] = (string)$filters['action_type'];
            $types .= 's';
        }
        if (!empty($filters['q'])) {
            $where[] = '(p.name LIKE ? OR pv.variant_name LIKE ? OR a.full_name LIKE ? OR im.notes LIKE ?)';
            $like = '%' . trim((string)$filters['q']) . '%';
            array_push($params, $like, $like, $like, $like);
            $types .= 'ssss';
        }

        $sql = "SELECT im.*, p.name AS product_name, pv.variant_name, a.full_name AS admin_name
                FROM inventory_movements im
                LEFT JOIN products p ON p.id = im.product_id
                LEFT JOIN product_variants pv ON pv.id = im.variant_id
                LEFT JOIN admins a ON a.id = im.admin_id";
        if ($where) {
            $sql .= ' WHERE ' . implode(' AND ', $where);
        }
        $sql .= ' ORDER BY im.id DESC LIMIT ?';
        $types .= 'i';
        $params[] = $limit;
        $stmt = $conn->prepare($sql);
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $res = $stmt->get_result();
        $rows = [];
        while ($row = $res->fetch_assoc()) {
            $rows[] = $row;
        }
        $stmt->close();
        return $rows;
    }
}
