<?php
// Influencer System v2 - aligned to agreed requirements
// - Full influencer data for admin create/edit
// - Self registration with pending status
// - Payments to influencer
// - Commission only on delivered orders
// - Commission settings come from promo_codes

if (!function_exists('infl_db')) {
    function infl_db()
    {
        global $conn, $mysqli, $db;
        if (isset($conn) && $conn instanceof mysqli) return $conn;
        if (isset($mysqli) && $mysqli instanceof mysqli) return $mysqli;
        if (isset($db) && $db instanceof mysqli) return $db;
        if (function_exists('db')) {
            $maybe = db();
            if ($maybe instanceof mysqli) return $maybe;
        }
        throw new RuntimeException('Database connection not found.');
    }
}

if (!function_exists('infl_h')) {
    function infl_h($v) { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('infl_redirect')) {
    function infl_redirect($url) { header('Location: '.$url); exit; }
}
if (!function_exists('infl_fetch_one')) {
    function infl_fetch_one($sql, $types = '', $params = []) {
        $db = infl_db();
        $stmt = $db->prepare($sql);
        if (!$stmt) throw new RuntimeException('Prepare failed: '.$db->error);
        if ($types !== '' && !empty($params)) $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $res = $stmt->get_result();
        $row = $res ? $res->fetch_assoc() : null;
        $stmt->close();
        return $row;
    }
}
if (!function_exists('infl_fetch_all')) {
    function infl_fetch_all($sql, $types = '', $params = []) {
        $db = infl_db();
        $stmt = $db->prepare($sql);
        if (!$stmt) throw new RuntimeException('Prepare failed: '.$db->error);
        if ($types !== '' && !empty($params)) $stmt->bind_param($types, ...$params);
        $stmt->execute();
        $res = $stmt->get_result();
        $rows = [];
        if ($res) while ($row = $res->fetch_assoc()) $rows[] = $row;
        $stmt->close();
        return $rows;
    }
}
if (!function_exists('infl_exec')) {
    function infl_exec($sql, $types = '', $params = []) {
        $db = infl_db();
        $stmt = $db->prepare($sql);
        if (!$stmt) throw new RuntimeException('Prepare failed: '.$db->error);
        if ($types !== '' && !empty($params)) $stmt->bind_param($types, ...$params);
        $ok = $stmt->execute();
        if (!$ok) {
            $err = $stmt->error;
            $stmt->close();
            throw new RuntimeException('Execute failed: '.$err);
        }
        $out = ['insert_id' => $stmt->insert_id, 'affected_rows' => $stmt->affected_rows];
        $stmt->close();
        return $out;
    }
}
if (!function_exists('infl_table_exists')) {
    function infl_table_exists($table) {
        $db = infl_db();
        $table = $db->real_escape_string((string)$table);
        $sql = "SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '{$table}' LIMIT 1";
        $res = $db->query($sql);
        if (!$res) return false;
        $row = $res->fetch_assoc();
        $res->close();
        return !empty($row);
    }
}
if (!function_exists('infl_column_exists')) {
    function infl_column_exists($table, $column) {
        $db = infl_db();
        $table = $db->real_escape_string((string)$table);
        $column = $db->real_escape_string((string)$column);
        $sql = "SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '{$table}' AND COLUMN_NAME = '{$column}' LIMIT 1";
        $res = $db->query($sql);
        if (!$res) return false;
        $row = $res->fetch_assoc();
        $res->close();
        return !empty($row);
    }
}
if (!function_exists('infl_schema_issues')) {
    function infl_schema_issues() {
        $issues = [];
        $checks = [
            ['table','influencers','جدول influencers غير موجود.'],
            ['table','influencer_payments','جدول influencer_payments غير موجود.'],
            ['table','influencer_payout_requests','جدول influencer_payout_requests غير موجود.'],
            ['table','influencer_levels','جدول influencer_levels غير موجود.'],
            ['table','influencer_level_benefits','جدول influencer_level_benefits غير موجود.'],
            ['column',['promo_codes','influencer_id'],'الحقل promo_codes.influencer_id غير موجود.'],
            ['column',['promo_codes','influencer_commission_type'],'الحقل promo_codes.influencer_commission_type غير موجود.'],
            ['column',['promo_codes','influencer_commission_value'],'الحقل promo_codes.influencer_commission_value غير موجود.'],
            ['column',['orders','influencer_id'],'الحقل orders.influencer_id غير موجود.'],
            ['column',['orders','influencer_code'],'الحقل orders.influencer_code غير موجود.'],
        ];
        foreach ($checks as $check) {
            if ($check[0] === 'table' && !infl_table_exists($check[1])) $issues[] = $check[2];
            if ($check[0] === 'column' && !infl_column_exists($check[1][0], $check[1][1])) $issues[] = $check[2];
        }
        return $issues;
    }
}
if (!function_exists('infl_prepare_result')) {
    function infl_prepare_result($success, $message, $data = []) {
        return ['success'=>(bool)$success, 'message'=>(string)$message, 'data'=>$data];
    }
}
if (!function_exists('infl_status_map')) {
    function infl_status_map() {
        return [1=>'نشط', 2=>'معلّق', 0=>'معطل'];
    }
}
if (!function_exists('infl_status_badge')) {
    function infl_status_badge($status) {
        $status = (int)$status;
        if ($status === 1) return '<span style="display:inline-block;padding:6px 10px;border-radius:999px;background:#dcfce7;color:#166534;font-size:12px;">نشط</span>';
        if ($status === 2) return '<span style="display:inline-block;padding:6px 10px;border-radius:999px;background:#fef3c7;color:#92400e;font-size:12px;">معلّق</span>';
        return '<span style="display:inline-block;padding:6px 10px;border-radius:999px;background:#fee2e2;color:#991b1b;font-size:12px;">معطل</span>';
    }
}
if (!function_exists('infl_money')) {
    function infl_money($amount) {
        return number_format((float)$amount, 0) . ' د.ع';
    }
}
if (!function_exists('infl_clean_code')) {
    function infl_clean_code($value) {
        $value = trim((string)$value);
        $value = preg_replace('/\s+/', '', $value);
        return strtoupper($value);
    }
}
if (!function_exists('infl_clean_insta')) {
    function infl_clean_insta($value) {
        $value = trim((string)$value);
        $value = ltrim($value, '@');
        return $value;
    }
}

if (!function_exists('infl_setting')) {
    function infl_setting($key, $default = '') {
        try {
            $row = infl_fetch_one('SELECT setting_value FROM settings WHERE setting_key = ? LIMIT 1', 's', [(string)$key]);
            if (!$row || !array_key_exists('setting_value', $row)) {
                return $default;
            }
            $value = $row['setting_value'];
            return $value === null ? $default : $value;
        } catch (Throwable $e) {
            return $default;
        }
    }
}
if (!function_exists('infl_setting_number')) {
    function infl_setting_number($key, $default = 0.0) {
        return (float)infl_setting($key, (string)$default);
    }
}
if (!function_exists('infl_generate_promo_code')) {
    function infl_generate_promo_code(string $name, string $phone, int $excludePromoId = 0): string {
        $digits = preg_replace('/\D+/', '', $phone);
        $suffix = $digits !== '' ? substr($digits, -6) : '';
        $base = 'INF' . ($suffix !== '' ? $suffix : strtoupper(substr(preg_replace('/[^A-Za-z0-9]+/', '', $name), 0, 6)));
        $base = infl_clean_code($base);
        if ($base === '') {
            $base = 'INF' . date('His');
        }
        $candidate = $base;
        $i = 1;
        while (infl_promo_code_exists($candidate, $excludePromoId)) {
            $candidate = $base . $i;
            $i++;
        }
        return $candidate;
    }
}
if (!function_exists('infl_registration_defaults')) {
    function infl_registration_defaults(): array {
        $discountType = in_array((string)infl_setting('influencer_registration_discount_type', 'percent'), ['percent', 'fixed'], true)
            ? (string)infl_setting('influencer_registration_discount_type', 'percent')
            : 'percent';
        $commissionType = in_array((string)infl_setting('influencer_registration_commission_type', 'percent'), ['percent', 'fixed'], true)
            ? (string)infl_setting('influencer_registration_commission_type', 'percent')
            : 'percent';
        return [
            'discount_type' => $discountType,
            'discount_value' => infl_setting_number('influencer_registration_discount_value', 0),
            'commission_type' => $commissionType,
            'commission_value' => infl_setting_number('influencer_registration_commission_value', 0),
            'minimum_order_amount' => infl_setting_number('influencer_registration_minimum_order_amount', 0),
            'promo_title_prefix' => trim((string)infl_setting('influencer_registration_promo_title_prefix', 'كود المؤثر - ')),
        ];
    }
}
if (!function_exists('infl_default_form')) {
    function infl_default_form() {
        $defaults = infl_registration_defaults();
        return [
            'name' => '',
            'login_code' => '',
            'phone' => '',
            'instagram_username' => '',
            'notes' => '',
            'status' => 1,
            'password' => '',
            'promo_title' => '',
            'promo_code' => '',
            'discount_type' => $defaults['discount_type'],
            'discount_value' => (string)$defaults['discount_value'],
            'minimum_order_amount' => (string)$defaults['minimum_order_amount'],
            'maximum_discount_amount' => '',
            'usage_limit' => '',
            'start_at' => '',
            'end_at' => '',
            'influencer_commission_type' => $defaults['commission_type'],
            'influencer_commission_value' => (string)$defaults['commission_value'],
            'promo_status' => 1,
            'promo_notes' => '',
        ];
    }
}
if (!function_exists('infl_exists_by')) {
    function infl_exists_by($field, $value, $excludeId = 0) {
        $allowed = ['login_code', 'instagram_username', 'phone'];
        if (!in_array($field, $allowed, true)) return false;
        $value = trim((string)$value);
        if ($value === '') return false;
        if ($excludeId > 0) {
            $row = infl_fetch_one("SELECT id FROM influencers WHERE {$field} = ? AND id <> ? LIMIT 1", 'si', [$value, $excludeId]);
        } else {
            $row = infl_fetch_one("SELECT id FROM influencers WHERE {$field} = ? LIMIT 1", 's', [$value]);
        }
        return !empty($row);
    }
}
if (!function_exists('infl_promo_code_exists')) {
    function infl_promo_code_exists($code, $excludePromoId = 0) {
        $code = infl_clean_code($code);
        if ($code === '') return false;
        if ($excludePromoId > 0) {
            $row = infl_fetch_one("SELECT id FROM promo_codes WHERE code = ? AND id <> ? LIMIT 1", 'si', [$code, $excludePromoId]);
        } else {
            $row = infl_fetch_one("SELECT id FROM promo_codes WHERE code = ? LIMIT 1", 's', [$code]);
        }
        return !empty($row);
    }
}
if (!function_exists('infl_find_influencer')) {
    function infl_find_influencer($id) {
        $sql = "SELECT i.*,
                       pc.id AS promo_id,
                       pc.title AS promo_title,
                       pc.code AS promo_code,
                       pc.discount_type,
                       pc.discount_value,
                       pc.minimum_order_amount,
                       pc.maximum_discount_amount,
                       pc.usage_limit,
                       pc.used_count,
                       pc.start_at,
                       pc.end_at,
                       pc.status AS promo_status,
                       pc.notes AS promo_notes,
                       pc.influencer_commission_type,
                       pc.influencer_commission_value
                FROM influencers i
                LEFT JOIN promo_codes pc ON pc.id = (
                    SELECT p2.id FROM promo_codes p2 WHERE p2.influencer_id = i.id ORDER BY p2.id ASC LIMIT 1
                )
                WHERE i.id = ? LIMIT 1";
        return infl_fetch_one($sql, 'i', [$id]);
    }
}
if (!function_exists('infl_validate_and_clean_form')) {
    function infl_validate_and_clean_form(array $data, $isCreate = true, $currentInfluencerId = 0, $currentPromoId = 0, $forcePending = false) {
        $name = trim((string)($data['name'] ?? ''));
        $phone = trim((string)($data['phone'] ?? ''));
        $phone = preg_replace('/\D+/', '', $phone) ?: $phone;
        $loginCode = infl_clean_code($data['login_code'] ?? '');
        if ($loginCode === '' && $phone !== '') {
            $loginCode = infl_clean_code($phone);
        }
        $instagram = infl_clean_insta($data['instagram_username'] ?? '');
        $notes = trim((string)($data['notes'] ?? ''));
        $password = (string)($data['password'] ?? '');
        $status = (int)($data['status'] ?? 1);
        if ($forcePending) $status = 2;
        if (!in_array($status, [0,1,2], true)) $status = 1;

        $defaults = infl_registration_defaults();
        $promoTitle = trim((string)($data['promo_title'] ?? ''));
        $promoCode = infl_clean_code($data['promo_code'] ?? '');
        $discountType = in_array(($data['discount_type'] ?? ''), ['percent','fixed'], true) ? $data['discount_type'] : (string)$defaults['discount_type'];
        $discountValue = (float)($data['discount_value'] ?? $defaults['discount_value']);
        $minimumOrderAmount = (float)($data['minimum_order_amount'] ?? $defaults['minimum_order_amount']);
        $maximumDiscountAmount = trim((string)($data['maximum_discount_amount'] ?? ''));
        $usageLimit = trim((string)($data['usage_limit'] ?? ''));
        $startAt = trim((string)($data['start_at'] ?? ''));
        $endAt = trim((string)($data['end_at'] ?? ''));
        $promoStatus = (int)($data['promo_status'] ?? 1) === 1 ? 1 : 0;
        $promoNotes = trim((string)($data['promo_notes'] ?? ''));
        $commissionType = in_array(($data['influencer_commission_type'] ?? ''), ['percent','fixed'], true) ? $data['influencer_commission_type'] : (string)$defaults['commission_type'];
        $commissionValue = (float)($data['influencer_commission_value'] ?? $defaults['commission_value']);

        if ($forcePending) {
            $discountType = (string)$defaults['discount_type'];
            $discountValue = (float)$defaults['discount_value'];
            $minimumOrderAmount = (float)$defaults['minimum_order_amount'];
            $commissionType = (string)$defaults['commission_type'];
            $commissionValue = (float)$defaults['commission_value'];
            if ($promoCode === '' && $phone !== '') {
                $promoCode = infl_generate_promo_code($name, $phone, $currentPromoId);
            }
        }

        if ($name === '') return infl_prepare_result(false, 'اسم المؤثر مطلوب');
        if ($loginCode === '') return infl_prepare_result(false, 'كود الدخول مطلوب');
        if ($phone === '') return infl_prepare_result(false, 'رقم الهاتف مطلوب');
        if ($isCreate && $password === '') return infl_prepare_result(false, 'كلمة المرور مطلوبة');
        if ($password !== '' && strlen($password) < 6) return infl_prepare_result(false, 'كلمة المرور لازم تكون 6 أحرف أو أكثر');
        if ($promoCode === '') return infl_prepare_result(false, 'كود الخصم/البروموكود مطلوب');
        if ($discountValue < 0) return infl_prepare_result(false, 'قيمة خصم الزبون غير صحيحة');
        if ($commissionValue < 0) return infl_prepare_result(false, 'قيمة عمولة المؤثر غير صحيحة');
        if ($discountType === 'percent' && $discountValue > 100) return infl_prepare_result(false, 'خصم الزبون كنسبة ما يصير أكثر من 100');
        if ($commissionType === 'percent' && $commissionValue > 100) return infl_prepare_result(false, 'عمولة المؤثر كنسبة ما تصير أكثر من 100');

        if (infl_exists_by('login_code', $loginCode, $currentInfluencerId)) return infl_prepare_result(false, 'كود الدخول مستخدم مسبقاً');
        if (infl_exists_by('phone', $phone, $currentInfluencerId)) return infl_prepare_result(false, 'رقم الهاتف مستخدم مسبقاً');
        if ($instagram !== '' && infl_exists_by('instagram_username', $instagram, $currentInfluencerId)) return infl_prepare_result(false, 'معرف الانستغرام مستخدم مسبقاً');
        if (infl_promo_code_exists($promoCode, $currentPromoId)) return infl_prepare_result(false, 'كود الخصم مستخدم مسبقاً');

        if ($promoTitle === '') $promoTitle = (($defaults['promo_title_prefix'] ?? 'كود المؤثر - ') !== '' ? (string)$defaults['promo_title_prefix'] : 'كود المؤثر - ') . $name;
        if ($maximumDiscountAmount === '') {
            $maximumDiscountAmount = null;
        } else {
            $maximumDiscountAmount = (float)$maximumDiscountAmount;
            if ($maximumDiscountAmount < 0) return infl_prepare_result(false, 'الحد الأعلى للخصم غير صحيح');
        }
        if ($usageLimit === '') {
            $usageLimit = null;
        } else {
            $usageLimit = (int)$usageLimit;
            if ($usageLimit < 0) return infl_prepare_result(false, 'حد الاستخدام غير صحيح');
        }
        if ($startAt !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$/', $startAt)) return infl_prepare_result(false, 'صيغة تاريخ البداية غير صحيحة');
        if ($endAt !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$/', $endAt)) return infl_prepare_result(false, 'صيغة تاريخ النهاية غير صحيحة');
        if ($startAt === '') $startAt = null;
        if ($endAt === '') $endAt = null;

        return infl_prepare_result(true, 'ok', [
            'name' => $name,
            'login_code' => $loginCode,
            'phone' => $phone,
            'instagram_username' => $instagram,
            'notes' => $notes,
            'status' => $status,
            'password_hash' => $password !== '' ? password_hash($password, PASSWORD_DEFAULT) : null,
            'promo_title' => $promoTitle,
            'promo_code' => $promoCode,
            'discount_type' => $discountType,
            'discount_value' => $discountValue,
            'minimum_order_amount' => $minimumOrderAmount,
            'maximum_discount_amount' => $maximumDiscountAmount,
            'usage_limit' => $usageLimit,
            'start_at' => $startAt,
            'end_at' => $endAt,
            'promo_status' => $promoStatus,
            'promo_notes' => $promoNotes,
            'influencer_commission_type' => $commissionType,
            'influencer_commission_value' => $commissionValue,
        ]);
    }
}
if (!function_exists('infl_create_influencer')) {
    function infl_create_influencer(array $data, $forcePending = false) {
        $valid = infl_validate_and_clean_form($data, true, 0, 0, $forcePending);
        if (!$valid['success']) return $valid;
        $c = $valid['data'];
        $db = infl_db();
        try {
            $db->begin_transaction();
            $r = infl_exec(
                "INSERT INTO influencers (name, login_code, password_hash, phone, instagram_username, notes, status, created_at, updated_at)
                 VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW())",
                'ssssssi',
                [$c['name'], $c['login_code'], $c['password_hash'], $c['phone'], $c['instagram_username'], $c['notes'], $c['status']]
            );
            $influencerId = (int)$r['insert_id'];
            infl_exec(
                "INSERT INTO promo_codes (title, code, discount_type, discount_value, minimum_order_amount, maximum_discount_amount, usage_limit, used_count, start_at, end_at, is_single_use_per_customer, status, notes, influencer_id, influencer_commission_type, influencer_commission_value, created_at, updated_at)
                 VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?, 0, ?, ?, ?, ?, ?, NOW(), NOW())",
                'sssddiissisisd',
                [$c['promo_title'], $c['promo_code'], $c['discount_type'], $c['discount_value'], $c['minimum_order_amount'], $c['maximum_discount_amount'] ?? 0, $c['usage_limit'] ?? 0, $c['start_at'], $c['end_at'], $c['promo_status'], $c['promo_notes'], $influencerId, $c['influencer_commission_type'], $c['influencer_commission_value']]
            );
            // fix nulls for optional numeric/date fields
            if ($c['maximum_discount_amount'] === null || $c['usage_limit'] === null || $c['start_at'] === null || $c['end_at'] === null) {
                $promoIdRow = infl_fetch_one("SELECT id FROM promo_codes WHERE influencer_id = ? ORDER BY id DESC LIMIT 1", 'i', [$influencerId]);
                $promoId = (int)($promoIdRow['id'] ?? 0);
                if ($promoId > 0) {
                    infl_exec(
                        "UPDATE promo_codes SET maximum_discount_amount=?, usage_limit=?, start_at=?, end_at=? WHERE id=?",
                        'dissi',
                        [$c['maximum_discount_amount'] ?? 0, $c['usage_limit'] ?? 0, $c['start_at'], $c['end_at'], $promoId]
                    );
                    if ($c['maximum_discount_amount'] === null || $c['usage_limit'] === null || $c['start_at'] === null || $c['end_at'] === null) {
                        $db->query("UPDATE promo_codes SET "
                            . ($c['maximum_discount_amount'] === null ? "maximum_discount_amount=NULL, " : "")
                            . ($c['usage_limit'] === null ? "usage_limit=NULL, " : "")
                            . ($c['start_at'] === null ? "start_at=NULL, " : "")
                            . ($c['end_at'] === null ? "end_at=NULL, " : "")
                            . "updated_at=updated_at WHERE id=".(int)$promoId);
                    }
                }
            }
            $db->commit();
            return infl_prepare_result(true, $forcePending ? 'تم إرسال طلب التسجيل وبقيت الحالة معلّقة لحين التأكيد' : 'تم إنشاء المؤثر بنجاح', ['id' => $influencerId]);
        } catch (Throwable $e) {
            $db->rollback();
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}
if (!function_exists('infl_update_influencer')) {
    function infl_update_influencer($id, array $data) {
        $current = infl_find_influencer($id);
        if (!$current) return infl_prepare_result(false, 'المؤثر غير موجود');
        $valid = infl_validate_and_clean_form($data, false, $id, (int)($current['promo_id'] ?? 0), false);
        if (!$valid['success']) return $valid;
        $c = $valid['data'];
        $db = infl_db();
        try {
            $db->begin_transaction();
            if ($c['password_hash']) {
                infl_exec("UPDATE influencers SET name=?, login_code=?, password_hash=?, phone=?, instagram_username=?, notes=?, status=?, updated_at=NOW() WHERE id=? LIMIT 1", 'ssssssii', [$c['name'], $c['login_code'], $c['password_hash'], $c['phone'], $c['instagram_username'], $c['notes'], $c['status'], $id]);
            } else {
                infl_exec("UPDATE influencers SET name=?, login_code=?, phone=?, instagram_username=?, notes=?, status=?, updated_at=NOW() WHERE id=? LIMIT 1", 'sssssii', [$c['name'], $c['login_code'], $c['phone'], $c['instagram_username'], $c['notes'], $c['status'], $id]);
            }
            if (!empty($current['promo_id'])) {
                infl_exec("UPDATE promo_codes SET title=?, code=?, discount_type=?, discount_value=?, minimum_order_amount=?, maximum_discount_amount=?, usage_limit=?, start_at=?, end_at=?, status=?, notes=?, influencer_commission_type=?, influencer_commission_value=?, updated_at=NOW() WHERE id=? LIMIT 1",
                    'sssddiississdi',
                    [$c['promo_title'], $c['promo_code'], $c['discount_type'], $c['discount_value'], $c['minimum_order_amount'], $c['maximum_discount_amount'] ?? 0, $c['usage_limit'] ?? 0, $c['start_at'], $c['end_at'], $c['promo_status'], $c['promo_notes'], $c['influencer_commission_type'], $c['influencer_commission_value'], (int)$current['promo_id']]
                );
                if ($c['maximum_discount_amount'] === null || $c['usage_limit'] === null || $c['start_at'] === null || $c['end_at'] === null) {
                    $db->query("UPDATE promo_codes SET "
                        . ($c['maximum_discount_amount'] === null ? "maximum_discount_amount=NULL, " : "")
                        . ($c['usage_limit'] === null ? "usage_limit=NULL, " : "")
                        . ($c['start_at'] === null ? "start_at=NULL, " : "")
                        . ($c['end_at'] === null ? "end_at=NULL, " : "")
                        . "updated_at=updated_at WHERE id=".(int)$current['promo_id']);
                }
            } else {
                infl_exec(
                    "INSERT INTO promo_codes (title, code, discount_type, discount_value, minimum_order_amount, maximum_discount_amount, usage_limit, used_count, start_at, end_at, is_single_use_per_customer, status, notes, influencer_id, influencer_commission_type, influencer_commission_value, created_at, updated_at)
                     VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?, 0, ?, ?, ?, ?, ?, NOW(), NOW())",
                    'sssddiissisisd',
                    [$c['promo_title'], $c['promo_code'], $c['discount_type'], $c['discount_value'], $c['minimum_order_amount'], $c['maximum_discount_amount'] ?? 0, $c['usage_limit'] ?? 0, $c['start_at'], $c['end_at'], $c['promo_status'], $c['promo_notes'], $id, $c['influencer_commission_type'], $c['influencer_commission_value']]
                );
            }
            $db->commit();
            return infl_prepare_result(true, 'تم تحديث المؤثر بنجاح');
        } catch (Throwable $e) {
            $db->rollback();
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}
if (!function_exists('infl_set_status')) {
    function infl_set_status($id, $status) {
        $status = (int)$status;
        if (!in_array($status, [0,1,2], true)) return infl_prepare_result(false, 'حالة غير صحيحة');
        try {
            infl_exec("UPDATE influencers SET status=?, updated_at=NOW() WHERE id=? LIMIT 1", 'ii', [$status, $id]);
            return infl_prepare_result(true, 'تم تحديث حالة المؤثر');
        } catch (Throwable $e) {
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}
if (!function_exists('infl_commission_sql')) {
    function infl_commission_sql($orderAlias='o', $promoAlias='pc') {
        return "CASE
            WHEN {$orderAlias}.order_status = 'delivered' AND {$promoAlias}.influencer_commission_type = 'percent' THEN GREATEST({$orderAlias}.total_amount - {$orderAlias}.delivery_fee, 0) * ({$promoAlias}.influencer_commission_value / 100)
            WHEN {$orderAlias}.order_status = 'delivered' AND {$promoAlias}.influencer_commission_type = 'fixed' THEN {$promoAlias}.influencer_commission_value
            ELSE 0 END";
    }
}
if (!function_exists('infl_get_stats')) {
    function infl_get_stats() {
        $stats = ['total'=>0,'active'=>0,'pending'=>0,'inactive'=>0,'delivered_orders'=>0,'earned'=>0,'paid'=>0,'remaining'=>0];
        if (infl_schema_issues()) return $stats;
        $row = infl_fetch_one("SELECT COUNT(*) total, SUM(status=1) active, SUM(status=2) pending, SUM(status=0) inactive FROM influencers");
        if ($row) {
            $stats['total'] = (int)$row['total'];
            $stats['active'] = (int)$row['active'];
            $stats['pending'] = (int)$row['pending'];
            $stats['inactive'] = (int)$row['inactive'];
        }
        $row2 = infl_fetch_one("SELECT COUNT(o.id) delivered_orders, COALESCE(SUM(".infl_commission_sql('o','pc')."),0) earned
            FROM orders o
            INNER JOIN promo_codes pc ON pc.id = o.promo_code_id
            WHERE pc.influencer_id IS NOT NULL AND o.order_status='delivered'");
        if ($row2) {
            $stats['delivered_orders'] = (int)$row2['delivered_orders'];
            $stats['earned'] = (float)$row2['earned'];
        }
        $row3 = infl_fetch_one("SELECT COALESCE(SUM(amount),0) paid FROM influencer_payments");
        $stats['paid'] = (float)($row3['paid'] ?? 0);
        $stats['remaining'] = max(0, $stats['earned'] - $stats['paid']);
        return $stats;
    }
}
if (!function_exists('infl_get_influencers')) {
    function infl_get_influencers(array $input = [], $page = 1, $perPage = 20) {
        $page = max(1, (int)$page);
        $offset = ($page-1)*$perPage;
        $filters = ['q'=>trim((string)($input['q'] ?? '')), 'status'=>(string)($input['status'] ?? '')];
        $where=[]; $types=''; $params=[];
        if ($filters['q'] !== '') {
            $q='%'.$filters['q'].'%';
            $where[]='(i.name LIKE ? OR i.login_code LIKE ? OR i.phone LIKE ? OR i.instagram_username LIKE ? OR pc.code LIKE ?)';
            $types.='sssss'; array_push($params,$q,$q,$q,$q,$q);
        }
        if (in_array($filters['status'], ['0','1','2'], true)) { $where[]='i.status=?'; $types.='i'; $params[]=(int)$filters['status']; }
        $whereSql = $where ? 'WHERE '.implode(' AND ',$where) : '';
        $count = infl_fetch_one("SELECT COUNT(*) total FROM influencers i LEFT JOIN promo_codes pc ON pc.id=(SELECT p2.id FROM promo_codes p2 WHERE p2.influencer_id=i.id ORDER BY p2.id ASC LIMIT 1) {$whereSql}", $types, $params);
        $total = (int)($count['total'] ?? 0);
        $sql = "SELECT i.*, pc.id promo_id, pc.code promo_code, pc.discount_type, pc.discount_value, pc.influencer_commission_type, pc.influencer_commission_value,
                   COALESCE((SELECT COUNT(o.id) FROM orders o INNER JOIN promo_codes pco ON pco.id=o.promo_code_id WHERE pco.influencer_id=i.id AND o.order_status='delivered'),0) delivered_orders,
                   COALESCE((SELECT SUM(".infl_commission_sql('o','pco').") FROM orders o INNER JOIN promo_codes pco ON pco.id=o.promo_code_id WHERE pco.influencer_id=i.id),0) earned_commission,
                   COALESCE((SELECT SUM(ip.amount) FROM influencer_payments ip WHERE ip.influencer_id=i.id),0) paid_commission
                FROM influencers i
                LEFT JOIN promo_codes pc ON pc.id=(SELECT p2.id FROM promo_codes p2 WHERE p2.influencer_id=i.id ORDER BY p2.id ASC LIMIT 1)
                {$whereSql}
                ORDER BY CASE WHEN i.status=2 THEN 0 ELSE 1 END, i.id DESC
                LIMIT {$perPage} OFFSET {$offset}";
        $rows = infl_fetch_all($sql, $types, $params);
        foreach ($rows as &$r) $r['remaining_commission'] = max(0, (float)$r['earned_commission'] - (float)$r['paid_commission']);
        unset($r);
        return ['rows'=>$rows,'filters'=>$filters,'total'=>$total,'page'=>$page,'pages'=>max(1,(int)ceil($total/$perPage))];
    }
}
if (!function_exists('infl_get_order_stats_for_one')) {
    function infl_get_order_stats_for_one($influencerId) {
        $row = infl_fetch_one("SELECT
                COUNT(o.id) total_orders,
                SUM(CASE WHEN o.order_status='delivered' THEN 1 ELSE 0 END) delivered_orders,
                COALESCE(SUM(".infl_commission_sql('o','pc')."),0) earned_commission
            FROM promo_codes pc
            LEFT JOIN orders o ON o.promo_code_id = pc.id
            WHERE pc.influencer_id=?", 'i', [$influencerId]);
        $paid = infl_get_payment_total($influencerId);
        return [
            'total_orders'=>(int)($row['total_orders'] ?? 0),
            'delivered_orders'=>(int)($row['delivered_orders'] ?? 0),
            'earned_commission'=>(float)($row['earned_commission'] ?? 0),
            'paid_commission'=>$paid,
            'remaining_commission'=>max(0, (float)($row['earned_commission'] ?? 0)-$paid),
        ];
    }
}
if (!function_exists('infl_get_recent_orders')) {
    function infl_get_recent_orders($influencerId, $limit = 25) {
        $limit = max(1, (int)$limit);
        $sql = "SELECT o.id, o.order_number, o.customer_name, o.customer_phone, o.subtotal, o.discount_value, o.delivery_fee, o.total_amount, o.payment_status, o.order_status, o.placed_at, o.delivered_at,
                       pc.code AS promo_code, pc.influencer_commission_type, pc.influencer_commission_value,
                       ".infl_commission_sql('o','pc')." AS commission_amount
                FROM orders o
                INNER JOIN promo_codes pc ON pc.id = o.promo_code_id
                WHERE pc.influencer_id=?
                ORDER BY CASE WHEN o.order_status='delivered' THEN 0 ELSE 1 END, o.id DESC
                LIMIT {$limit}";
        return infl_fetch_all($sql, 'i', [$influencerId]);
    }
}
if (!function_exists('infl_get_payments')) {
    function infl_get_payments($influencerId, $limit = 50) {
        $limit = max(1, (int)$limit);
        return infl_fetch_all("SELECT * FROM influencer_payments WHERE influencer_id=? ORDER BY pay_date DESC, id DESC LIMIT {$limit}", 'i', [$influencerId]);
    }
}
if (!function_exists('infl_get_payment_total')) {
    function infl_get_payment_total($influencerId) {
        $row = infl_fetch_one("SELECT COALESCE(SUM(amount),0) total FROM influencer_payments WHERE influencer_id=?", 'i', [$influencerId]);
        return (float)($row['total'] ?? 0);
    }
}
if (!function_exists('infl_save_payment')) {
    function infl_save_payment($influencerId, array $data) {
        $amount = (float)($data['amount'] ?? 0);
        $payDate = trim((string)($data['pay_date'] ?? ''));
        $note = trim((string)($data['note'] ?? ''));
        if ($amount <= 0) return infl_prepare_result(false, 'مبلغ الدفعة لازم يكون أكبر من صفر');
        if ($payDate === '' || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $payDate)) return infl_prepare_result(false, 'تاريخ الدفع غير صحيح');
        try {
            infl_exec("INSERT INTO influencer_payments (influencer_id, amount, pay_date, note, created_at) VALUES (?, ?, ?, ?, NOW())", 'idss', [$influencerId, $amount, $payDate, $note]);
            return infl_prepare_result(true, 'تم تسجيل الدفعة بنجاح');
        } catch (Throwable $e) {
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}
if (!function_exists('infl_delete_payment')) {
    function infl_delete_payment($paymentId) {
        try { infl_exec("DELETE FROM influencer_payments WHERE id=? LIMIT 1", 'i', [$paymentId]); return infl_prepare_result(true, 'تم حذف الدفعة'); }
        catch (Throwable $e) { return infl_prepare_result(false, $e->getMessage()); }
    }
}

if (!function_exists('infl_money_plain')) {
    function infl_money_plain($amount) {
        return number_format((float)$amount, 0) . ' د.ع';
    }
}
if (!function_exists('infl_admin_id')) {
    function infl_admin_id(): ?int {
        if (function_exists('current_admin_id')) {
            $id = (int)current_admin_id();
            return $id > 0 ? $id : null;
        }
        return null;
    }
}
if (!function_exists('infl_setting_set')) {
    function infl_setting_set(string $key, $value, string $group = 'influencer') {
        $row = infl_fetch_one('SELECT id FROM settings WHERE setting_key = ? ORDER BY id ASC LIMIT 1', 's', [$key]);
        if ($row && !empty($row['id'])) {
            infl_exec('UPDATE settings SET setting_value = ?, setting_group = ?, updated_at = NOW() WHERE id = ? LIMIT 1', 'ssi', [(string)$value, $group, (int)$row['id']]);
            return;
        }
        infl_exec('INSERT INTO settings (setting_key, setting_value, setting_group, created_at, updated_at) VALUES (?, ?, ?, NOW(), NOW())', 'sss', [$key, (string)$value, $group]);
    }
}
if (!function_exists('infl_payout_tables_ready')) {
    function infl_payout_tables_ready() {
        return infl_table_exists('influencer_payout_requests') && infl_table_exists('influencer_payments') && infl_table_exists('influencers');
    }
}
if (!function_exists('infl_levels_tables_ready')) {
    function infl_levels_tables_ready() {
        return infl_table_exists('influencer_levels') && infl_table_exists('influencer_level_benefits') && infl_column_exists('influencers', 'level_id');
    }
}
if (!function_exists('infl_sales_window')) {
    function infl_sales_window(): array {
        return [
            'start' => trim((string)infl_setting('influencer_levels_period_start', '')),
            'end' => trim((string)infl_setting('influencer_levels_period_end', '')),
        ];
    }
}
if (!function_exists('infl_set_sales_window')) {
    function infl_set_sales_window($start, $end) {
        $start = trim((string)$start);
        $end = trim((string)$end);
        if ($start !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $start)) return infl_prepare_result(false, 'صيغة بداية الفترة غير صحيحة');
        if ($end !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $end)) return infl_prepare_result(false, 'صيغة نهاية الفترة غير صحيحة');
        if ($start !== '' && $end !== '' && $start > $end) return infl_prepare_result(false, 'بداية الفترة لازم تكون قبل أو تساوي نهاية الفترة');
        try {
            infl_setting_set('influencer_levels_period_start', $start, 'influencer');
            infl_setting_set('influencer_levels_period_end', $end, 'influencer');
            return infl_prepare_result(true, 'تم حفظ نافذة تقييم المستويات');
        } catch (Throwable $e) {
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}
if (!function_exists('infl_load_level_benefits')) {
    function infl_load_level_benefits(array $levelIds): array {
        $levelIds = array_values(array_filter(array_map('intval', $levelIds), fn($v) => $v > 0));
        if (!$levelIds) return [];
        $placeholders = implode(',', array_fill(0, count($levelIds), '?'));
        $types = str_repeat('i', count($levelIds));
        $rows = infl_fetch_all("SELECT * FROM influencer_level_benefits WHERE level_id IN ({$placeholders}) ORDER BY sort_order ASC, id ASC", $types, $levelIds);
        $out = [];
        foreach ($rows as $row) {
            $lid = (int)($row['level_id'] ?? 0);
            if (!isset($out[$lid])) $out[$lid] = [];
            $out[$lid][] = $row;
        }
        return $out;
    }
}
if (!function_exists('infl_get_levels')) {
    function infl_get_levels() {
        if (!infl_levels_tables_ready()) return [];
        $levels = infl_fetch_all('SELECT * FROM influencer_levels ORDER BY sort_order ASC, sales_min ASC, id ASC');
        if (!$levels) return [];
        $benefits = infl_load_level_benefits(array_column($levels, 'id'));
        foreach ($levels as &$level) {
            $level['benefits'] = $benefits[(int)$level['id']] ?? [];
        }
        unset($level);
        return $levels;
    }
}
if (!function_exists('infl_find_level')) {
    function infl_find_level($id) {
        if ((int)$id <= 0 || !infl_levels_tables_ready()) return null;
        $level = infl_fetch_one('SELECT * FROM influencer_levels WHERE id = ? LIMIT 1', 'i', [(int)$id]);
        if (!$level) return null;
        $level['benefits'] = infl_load_level_benefits([(int)$id])[(int)$id] ?? [];
        return $level;
    }
}
if (!function_exists('infl_normalize_benefits_text')) {
    function infl_normalize_benefits_text($text): array {
        $lines = preg_split('/
|
|
/', (string)$text) ?: [];
        $items = [];
        foreach ($lines as $line) {
            $line = trim((string)$line);
            if ($line !== '') $items[] = $line;
        }
        return $items;
    }
}
if (!function_exists('infl_save_level')) {
    function infl_save_level(array $data, int $levelId = 0) {
        if (!infl_levels_tables_ready()) return infl_prepare_result(false, 'جداول المستويات غير جاهزة');
        $title = trim((string)($data['title'] ?? ''));
        $salesMin = (float)($data['sales_min'] ?? 0);
        $salesMaxRaw = trim((string)($data['sales_max'] ?? ''));
        $salesMax = $salesMaxRaw === '' ? null : (float)$salesMaxRaw;
        $sortOrder = (int)($data['sort_order'] ?? 0);
        $isActive = isset($data['is_active']) ? 1 : 0;
        $benefits = infl_normalize_benefits_text($data['benefits_text'] ?? '');
        if ($title === '') return infl_prepare_result(false, 'اسم المستوى مطلوب');
        if ($salesMin < 0) return infl_prepare_result(false, 'الحد الأدنى غير صحيح');
        if ($salesMax !== null && $salesMax < $salesMin) return infl_prepare_result(false, 'الحد الأعلى لازم يكون أكبر أو يساوي الحد الأدنى');
        $db = infl_db();
        try {
            $db->begin_transaction();
            if ($levelId > 0) {
                infl_exec('UPDATE influencer_levels SET title = ?, sales_min = ?, sales_max = ?, sort_order = ?, is_active = ?, updated_at = NOW() WHERE id = ? LIMIT 1', 'sddiii', [$title, $salesMin, $salesMax ?? 0, $sortOrder, $isActive, $levelId]);
                if ($salesMax === null) {
                    $db->query('UPDATE influencer_levels SET sales_max = NULL WHERE id = ' . (int)$levelId . ' LIMIT 1');
                }
                infl_exec('DELETE FROM influencer_level_benefits WHERE level_id = ?', 'i', [$levelId]);
            } else {
                $r = infl_exec('INSERT INTO influencer_levels (title, sales_min, sales_max, sort_order, is_active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, NOW(), NOW())', 'sddii', [$title, $salesMin, $salesMax ?? 0, $sortOrder, $isActive]);
                $levelId = (int)$r['insert_id'];
                if ($salesMax === null) {
                    $db->query('UPDATE influencer_levels SET sales_max = NULL WHERE id = ' . (int)$levelId . ' LIMIT 1');
                }
            }
            $i = 1;
            foreach ($benefits as $benefit) {
                infl_exec('INSERT INTO influencer_level_benefits (level_id, benefit_type, benefit_value, display_text, sort_order, created_at) VALUES (?, ?, ?, ?, ?, NOW())', 'isssi', [$levelId, 'note', $benefit, $benefit, $i]);
                $i++;
            }
            $db->commit();
            return infl_prepare_result(true, $levelId > 0 && !empty($data['level_id']) ? 'تم حفظ المستوى بنجاح' : 'تم إنشاء المستوى بنجاح', ['id' => $levelId]);
        } catch (Throwable $e) {
            $db->rollback();
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}
if (!function_exists('infl_delete_level')) {
    function infl_delete_level($id) {
        $id = (int)$id;
        if ($id <= 0) return infl_prepare_result(false, 'المستوى غير صحيح');
        $db = infl_db();
        try {
            $db->begin_transaction();
            infl_exec('UPDATE influencers SET level_id = NULL, updated_at = NOW() WHERE level_id = ?', 'i', [$id]);
            infl_exec('DELETE FROM influencer_level_benefits WHERE level_id = ?', 'i', [$id]);
            infl_exec('DELETE FROM influencer_levels WHERE id = ? LIMIT 1', 'i', [$id]);
            $db->commit();
            return infl_prepare_result(true, 'تم حذف المستوى');
        } catch (Throwable $e) {
            $db->rollback();
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}
if (!function_exists('infl_influencer_sales_in_window')) {
    function infl_influencer_sales_in_window(int $influencerId, array $window): float {
        $where = ["(o.influencer_id = ? OR pc.influencer_id = ?)", "o.order_status = 'delivered'", "o.payment_status = 'paid'"];
        $types = 'ii';
        $params = [$influencerId, $influencerId];
        if (!empty($window['start'])) { $where[] = 'DATE(COALESCE(o.delivered_at, o.updated_at, o.created_at)) >= ?'; $types .= 's'; $params[] = $window['start']; }
        if (!empty($window['end'])) { $where[] = 'DATE(COALESCE(o.delivered_at, o.updated_at, o.created_at)) <= ?'; $types .= 's'; $params[] = $window['end']; }
        $sql = 'SELECT COALESCE(SUM(o.total_amount),0) AS total_sales FROM orders o LEFT JOIN promo_codes pc ON pc.id = o.promo_code_id WHERE ' . implode(' AND ', $where);
        $row = infl_fetch_one($sql, $types, $params);
        return (float)($row['total_sales'] ?? 0);
    }
}
if (!function_exists('infl_match_level_for_sales')) {
    function infl_match_level_for_sales(float $sales, array $levels) {
        $matched = null;
        foreach ($levels as $level) {
            if ((int)($level['is_active'] ?? 0) !== 1) continue;
            $min = (float)($level['sales_min'] ?? 0);
            $max = isset($level['sales_max']) && $level['sales_max'] !== null ? (float)$level['sales_max'] : null;
            if ($sales < $min) continue;
            if ($max !== null && $sales > $max) continue;
            $matched = $level;
        }
        return $matched;
    }
}
if (!function_exists('infl_refresh_all_influencer_levels')) {
    function infl_refresh_all_influencer_levels() {
        if (!infl_levels_tables_ready()) return infl_prepare_result(false, 'جداول المستويات غير جاهزة');
        $levels = infl_get_levels();
        $influencers = infl_fetch_all('SELECT id FROM influencers ORDER BY id ASC');
        $window = infl_sales_window();
        $updated = 0;
        foreach ($influencers as $row) {
            $id = (int)$row['id'];
            $sales = infl_influencer_sales_in_window($id, $window);
            $matched = infl_match_level_for_sales($sales, $levels);
            $levelId = $matched ? (int)$matched['id'] : null;
            if ($levelId !== null) {
                infl_exec('UPDATE influencers SET level_id = ?, updated_at = NOW() WHERE id = ? LIMIT 1', 'ii', [$levelId, $id]);
            } else {
                infl_db()->query('UPDATE influencers SET level_id = NULL, updated_at = NOW() WHERE id = ' . $id . ' LIMIT 1');
            }
            $updated++;
        }
        return infl_prepare_result(true, 'تم تحديث مستويات المؤثرين (' . $updated . ')');
    }
}
if (!function_exists('infl_get_balance_summary')) {
    function infl_get_balance_summary($influencerId) {
        $influencerId = (int)$influencerId;
        $stats = infl_get_order_stats_for_one($influencerId);
        $reservedRow = infl_fetch_one("SELECT COALESCE(SUM(requested_amount),0) AS total FROM influencer_payout_requests WHERE influencer_id = ? AND status IN ('pending','approved')", 'i', [$influencerId]);
        $reserved = (float)($reservedRow['total'] ?? 0);
        $remaining = (float)($stats['remaining_commission'] ?? 0);
        return [
            'earned_commission' => (float)($stats['earned_commission'] ?? 0),
            'paid_commission' => (float)($stats['paid_commission'] ?? 0),
            'remaining_commission' => $remaining,
            'reserved_in_requests' => $reserved,
            'available_to_request' => max(0, $remaining - $reserved),
        ];
    }
}
if (!function_exists('infl_get_payout_request_stats')) {
    function infl_get_payout_request_stats() {
        $stats = [
            'pending_count' => 0, 'pending_amount' => 0,
            'approved_count' => 0, 'approved_amount' => 0,
            'paid_count' => 0, 'paid_amount' => 0,
            'rejected_count' => 0,
        ];
        if (!infl_payout_tables_ready()) return $stats;
        $row = infl_fetch_one("SELECT
            SUM(CASE WHEN status='pending' THEN 1 ELSE 0 END) AS pending_count,
            SUM(CASE WHEN status='pending' THEN requested_amount ELSE 0 END) AS pending_amount,
            SUM(CASE WHEN status='approved' THEN 1 ELSE 0 END) AS approved_count,
            SUM(CASE WHEN status='approved' THEN requested_amount ELSE 0 END) AS approved_amount,
            SUM(CASE WHEN status='paid' THEN 1 ELSE 0 END) AS paid_count,
            SUM(CASE WHEN status='paid' THEN requested_amount ELSE 0 END) AS paid_amount,
            SUM(CASE WHEN status='rejected' THEN 1 ELSE 0 END) AS rejected_count
            FROM influencer_payout_requests");
        if ($row) {
            foreach ($stats as $k => $v) {
                $stats[$k] = str_contains($k, '_count') ? (int)($row[$k] ?? 0) : (float)($row[$k] ?? 0);
            }
        }
        return $stats;
    }
}
if (!function_exists('infl_get_payout_requests')) {
    function infl_get_payout_requests($input = [], $page = 1, $perPage = 20) {
        $page = max(1, (int)$page);
        $offset = ($page - 1) * $perPage;
        $filters = ['q' => trim((string)($input['q'] ?? '')), 'status' => trim((string)($input['status'] ?? ''))];
        $where = [];
        $types = '';
        $params = [];
        if ($filters['q'] !== '') {
            $q = '%' . $filters['q'] . '%';
            $where[] = '(i.name LIKE ? OR i.phone LIKE ? OR i.login_code LIKE ?)';
            $types .= 'sss';
            array_push($params, $q, $q, $q);
        }
        if (in_array($filters['status'], ['pending','approved','paid','rejected'], true)) {
            $where[] = 'r.status = ?';
            $types .= 's';
            $params[] = $filters['status'];
        }
        $whereSql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';
        $count = infl_fetch_one("SELECT COUNT(*) AS total FROM influencer_payout_requests r INNER JOIN influencers i ON i.id = r.influencer_id {$whereSql}", $types, $params);
        $total = (int)($count['total'] ?? 0);
        $rows = infl_fetch_all("SELECT r.*, i.name AS influencer_name, i.phone AS influencer_phone, i.login_code AS influencer_login_code FROM influencer_payout_requests r INNER JOIN influencers i ON i.id = r.influencer_id {$whereSql} ORDER BY CASE r.status WHEN 'pending' THEN 0 WHEN 'approved' THEN 1 WHEN 'paid' THEN 2 ELSE 3 END, r.id DESC LIMIT {$perPage} OFFSET {$offset}", $types, $params);
        return ['rows' => $rows, 'filters' => $filters, 'total' => $total, 'page' => $page, 'pages' => max(1, (int)ceil($total / $perPage))];
    }
}
if (!function_exists('infl_find_payout_request')) {
    function infl_find_payout_request($requestId) {
        $requestId = (int)$requestId;
        if ($requestId <= 0) return null;
        return infl_fetch_one('SELECT r.*, i.name AS influencer_name, i.phone AS influencer_phone, i.login_code AS influencer_login_code FROM influencer_payout_requests r INNER JOIN influencers i ON i.id = r.influencer_id WHERE r.id = ? LIMIT 1', 'i', [$requestId]);
    }
}
if (!function_exists('infl_update_payout_request_status')) {
    function infl_update_payout_request_status($requestId, $action, $adminNote = '') {
        $requestId = (int)$requestId;
        $action = trim((string)$action);
        $request = infl_find_payout_request($requestId);
        if (!$request) return infl_prepare_result(false, 'طلب السحب غير موجود');
        if (!in_array($action, ['approved','paid','rejected'], true)) return infl_prepare_result(false, 'الإجراء غير صحيح');
        $db = infl_db();
        $adminId = infl_admin_id();
        try {
            $db->begin_transaction();
            if ($action === 'approved') {
                infl_exec("UPDATE influencer_payout_requests SET status='approved', admin_note=?, approved_at=NOW(), updated_at=NOW() WHERE id=? LIMIT 1", 'si', [$adminNote, $requestId]);
                $message = 'تم اعتماد طلب السحب';
            } elseif ($action === 'rejected') {
                infl_exec("UPDATE influencer_payout_requests SET status='rejected', admin_note=?, updated_at=NOW() WHERE id=? LIMIT 1", 'si', [$adminNote, $requestId]);
                $message = 'تم رفض طلب السحب';
            } else {
                infl_exec("UPDATE influencer_payout_requests SET status='paid', admin_note=?, approved_at=COALESCE(approved_at, NOW()), paid_at=NOW(), paid_by_admin_id=?, updated_at=NOW() WHERE id=? LIMIT 1", 'sii', [$adminNote, $adminId ?? 0, $requestId]);
                $payment = infl_fetch_one('SELECT id FROM influencer_payments WHERE payout_request_id = ? LIMIT 1', 'i', [$requestId]);
                if (!$payment) {
                    infl_exec('INSERT INTO influencer_payments (influencer_id, amount, pay_date, note, payout_request_id, created_by_admin_id, created_at) VALUES (?, ?, CURDATE(), ?, ?, ?, NOW())', 'idsii', [(int)$request['influencer_id'], (float)$request['requested_amount'], $adminNote !== '' ? $adminNote : ('دفعة مرتبطة بطلب السحب #' . $requestId), $requestId, $adminId ?? 0]);
                }
                $message = 'تم تأشير طلب السحب كمدفوع وإنشاء سجل دفعة';
            }
            $db->commit();
            return infl_prepare_result(true, $message);
        } catch (Throwable $e) {
            $db->rollback();
            return infl_prepare_result(false, $e->getMessage());
        }
    }
}

