<?php
/** Admin plan categories and catalog management - v15 traffic packages */
require_once 'config.php';
require_once 'plan_price_helper.php';
header('Content-Type: application/json; charset=utf-8');
$input = json_decode(file_get_contents('php://input'), true) ?: $_REQUEST;
$userId = miniapp_require_admin();

function planEnsureTrafficColumns(PDO $pdo): void {
    try { $pdo->exec("CREATE TABLE IF NOT EXISTS plan_categories (id INT AUTO_INCREMENT PRIMARY KEY, code VARCHAR(32) NOT NULL UNIQUE, service_type VARCHAR(30) NOT NULL DEFAULT 'openvpn_l2tp', service_name VARCHAR(100) NULL, name VARCHAR(100) NOT NULL, months INT NOT NULL DEFAULT 1, traffic_type VARCHAR(20) NOT NULL DEFAULT 'unlimited', traffic_limit_gb INT UNSIGNED NULL, is_active TINYINT(1) DEFAULT 1, display_order INT DEFAULT 0, sort_order INT NOT NULL DEFAULT 0, deleted_at DATETIME NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"); } catch(Throwable $e){}
    foreach ([
        "ALTER TABLE plan_categories ADD COLUMN service_type VARCHAR(30) NOT NULL DEFAULT 'openvpn_l2tp' AFTER code",
        "ALTER TABLE plan_categories ADD COLUMN service_name VARCHAR(100) NULL AFTER service_type",
        "ALTER TABLE plan_categories ADD COLUMN traffic_type VARCHAR(20) NOT NULL DEFAULT 'unlimited' AFTER months",
        "ALTER TABLE plan_categories ADD COLUMN traffic_limit_gb INT UNSIGNED NULL AFTER traffic_type",
        "ALTER TABLE plans ADD COLUMN service_name VARCHAR(100) NULL AFTER protocol",
        "ALTER TABLE plans ADD COLUMN traffic_type VARCHAR(20) NOT NULL DEFAULT 'unlimited' AFTER protocol",
        "ALTER TABLE plans ADD COLUMN traffic_limit_gb INT UNSIGNED NULL AFTER traffic_type",
        "ALTER TABLE plans ADD COLUMN purchase_price INT NOT NULL DEFAULT 0 AFTER price",
        "ALTER TABLE credentials ADD COLUMN traffic_limit_gb INT UNSIGNED NULL AFTER traffic_type",
        "ALTER TABLE orders ADD COLUMN traffic_type VARCHAR(20) NOT NULL DEFAULT 'unlimited' AFTER requested_seats",
        "ALTER TABLE orders ADD COLUMN traffic_limit_gb INT UNSIGNED NULL AFTER traffic_type",
        "ALTER TABLE waiting_queue ADD COLUMN traffic_type VARCHAR(20) NOT NULL DEFAULT 'unlimited' AFTER requested_seats",
        "ALTER TABLE waiting_queue ADD COLUMN traffic_limit_gb INT UNSIGNED NULL AFTER traffic_type",
        "ALTER TABLE plans MODIFY duration VARCHAR(32) NOT NULL DEFAULT '1M'",
        "ALTER TABLE credentials MODIFY duration VARCHAR(32) NOT NULL DEFAULT '1M'",
        "ALTER TABLE orders MODIFY duration VARCHAR(32) NOT NULL DEFAULT '1M'",
        "ALTER TABLE waiting_queue MODIFY duration VARCHAR(32) NOT NULL DEFAULT '1M'",
        "ALTER TABLE plans ADD COLUMN category_id INT NULL AFTER id",
    ] as $sql) {
        try {
            if (preg_match('/^ALTER\s+TABLE\s+`?([a-zA-Z0-9_]+)`?\s+ADD\s+COLUMN\s+`?([a-zA-Z0-9_]+)`?/i', $sql, $m)
                && function_exists('gemacc_column_exists') && gemacc_column_exists($pdo, $m[1], $m[2])) {
                continue;
            }
            $pdo->exec($sql);
        } catch(Throwable $e){}
    }
    try { $pdo->exec("UPDATE plan_categories SET traffic_type='unlimited' WHERE traffic_type IS NULL OR traffic_type=''"); } catch(Throwable $e){}
    try { $pdo->exec("UPDATE plans p LEFT JOIN plan_categories pc ON pc.id=p.category_id SET p.traffic_type=COALESCE(pc.traffic_type,'unlimited'), p.traffic_limit_gb=pc.traffic_limit_gb WHERE p.traffic_type IS NULL OR p.traffic_type='' OR (p.traffic_type='unlimited' AND pc.traffic_type='limited')"); } catch(Throwable $e){}
}
function catBaseName(int $m): string { $names=[1=>'یک‌ماهه',2=>'دوماهه',3=>'سه‌ماهه',4=>'چهارماهه',5=>'پنج‌ماهه',6=>'شش‌ماهه',7=>'هفت‌ماهه',8=>'هشت‌ماهه',9=>'نه‌ماهه',10=>'ده‌ماهه',11=>'یازده‌ماهه',12=>'یک‌ساله']; return $names[$m] ?? ($m.' ماهه'); }
function trafficLabel(array $r): string { return (($r['traffic_type']??'unlimited')==='limited') ? ('حجمی '.(int)($r['traffic_limit_gb']??0).' گیگ') : 'نامحدود'; }

function adminNormalizeServiceType(string $raw, string $hint=''): string {
    $s = function_exists('mb_strtolower') ? mb_strtolower(trim($raw), 'UTF-8') : strtolower(trim($raw));
    $h = function_exists('mb_strtolower') ? mb_strtolower(trim($hint), 'UTF-8') : strtolower(trim($hint));
    if (in_array($s, ['windscribe','ws','ویندسکرایب'], true) || str_contains($h, 'windscribe') || str_contains($h, 'ویندسکرایب')) return 'windscribe';
    if (in_array($s, ['expressvpn','express','اکسپرس','express vpn'], true) || str_contains($h, 'express') || str_contains($h, 'اکسپرس')) return 'expressvpn';
    if (in_array($s, ['v2ray','v2','vmess','vless','trojan','ویتوری','وی تو ری','وی‌تو‌ری'], true) || str_contains($h, 'v2ray') || str_contains($h, 'vmess') || str_contains($h, 'vless') || str_contains($h, 'trojan') || str_contains($h, 'ویتوری') || str_contains($h, 'وی تو ری') || str_contains($h, 'وی‌تو‌ری')) return 'v2ray';
    return 'openvpn_l2tp';
}
function adminServiceDefaultName(string $serviceType, string $fallback=''): string {
    $fallback = trim($fallback);
    if ($fallback !== '') return $fallback;
    return $serviceType === 'windscribe' ? 'Windscribe' : ($serviceType === 'expressvpn' ? 'ExpressVPN' : ($serviceType === 'v2ray' ? 'V2Ray' : 'OpenVPN | L2TP'));
}
function adminServicePrefix(string $serviceType): string {
    return $serviceType === 'windscribe' ? 'WS_' : ($serviceType === 'expressvpn' ? 'EXP_' : ($serviceType === 'v2ray' ? 'V2_' : 'OVPN_'));
}
function makeCatCode(int $months, string $trafficType, ?int $gb): string { return $trafficType==='limited' ? ($months.'M_L'.max(1,(int)$gb).'G') : ($months.'M_U'); }
planEnsureTrafficColumns($pdo);

if ($_SERVER['REQUEST_METHOD']==='GET') {
    $cats=$pdo->query("SELECT *, CASE WHEN service_type IN ('windscribe','expressvpn','v2ray') THEN CONCAT(name,' - ',COALESCE(NULLIF(service_name,''), CASE WHEN service_type='windscribe' THEN 'Windscribe' WHEN service_type='v2ray' THEN 'V2Ray' ELSE 'ExpressVPN' END)) WHEN traffic_type='limited' THEN CONCAT(name,' - حجمی ',COALESCE(traffic_limit_gb,0),' گیگ') ELSE CONCAT(name,' - ',COALESCE(NULLIF(service_name,''),'OpenVPN | L2TP')) END AS full_name FROM plan_categories WHERE deleted_at IS NULL ORDER BY months, traffic_type DESC, traffic_limit_gb, display_order, sort_order, id")->fetchAll(PDO::FETCH_ASSOC);
    $plans=$pdo->query("SELECT p.*, pc.name category_name, pc.code category_code, pc.service_type category_service_type, pc.service_name category_service_name, pc.months category_months, pc.traffic_type category_traffic_type, pc.traffic_limit_gb category_traffic_limit_gb, CASE WHEN COALESCE(p.traffic_type,pc.traffic_type)='limited' THEN CONCAT('حجمی ',COALESCE(p.traffic_limit_gb,pc.traffic_limit_gb,0),' گیگ') ELSE 'نامحدود' END AS traffic_label FROM plans p LEFT JOIN plan_categories pc ON pc.id=p.category_id WHERE p.deleted_at IS NULL AND (p.category_id IS NULL OR pc.id IS NOT NULL) ORDER BY COALESCE(pc.months,p.months), COALESCE(pc.traffic_type,p.traffic_type) DESC, COALESCE(pc.traffic_limit_gb,p.traffic_limit_gb), p.display_order, p.id")->fetchAll(PDO::FETCH_ASSOC);
    foreach($plans as &$p){ $p['purchase_price']=(int)($p['purchase_price'] ?? 0); $p['service_type']=adminNormalizeServiceType((string)($p['protocol'] ?: ($p['category_service_type'] ?? 'openvpn_l2tp')), (string)(($p['service_name'] ?? '').' '.($p['category_service_name'] ?? '').' '.($p['category_name'] ?? '').' '.($p['title'] ?? ''))); $p['service_label']=adminServiceDefaultName($p['service_type'], (string)($p['service_name'] ?: ($p['category_service_name'] ?? ''))); $p['tier_label']=$p['title']; $p['users']=(int)($p['user_count'] ?: $p['seats'] ?: 1); $p['traffic_type']=$p['traffic_type'] ?: ($p['category_traffic_type'] ?? 'unlimited'); $p['traffic_limit_gb']=$p['traffic_limit_gb'] ?? ($p['category_traffic_limit_gb'] ?? null); $unitInfo=gemacc_plan_apply_unit_price_fields($p); $p['total_price']=(int)$unitInfo['total_price']; $p['customer_price']=(int)$unitInfo['unit_sale_price']; $p['unit_sale_price']=(int)$unitInfo['unit_sale_price']; $p['unit_price_divisor']=(int)$unitInfo['unit_price_divisor']; $p['is_unit_price']=(int)$unitInfo['is_unit_price']; $p['unit_purchase_price']=(int)$unitInfo['unit_purchase_price']; $p['price_formatted']=money((int)$p['price']); $p['customer_price_formatted']=money((int)$p['customer_price']); $p['purchase_price_formatted']=money((int)$p['purchase_price']); $p['profit_per_sale']=max(0,(int)$p['customer_price']-(int)$p['unit_purchase_price']); }
    echo json_encode(['ok'=>true,'data'=>['categories'=>$cats,'plans'=>$plans]], JSON_UNESCAPED_UNICODE); exit;
}
$a=$input['action'] ?? '';
if ($a==='add_category') {
    $months=(int)($input['months']??1); if($months<1||$months>12)$months=1;
    $trafficType=strtolower(trim((string)($input['traffic_type']??'unlimited'))); if(!in_array($trafficType,['unlimited','limited'],true)) $trafficType='unlimited';
    $gb = $trafficType==='limited' ? max(1,(int)($input['traffic_limit_gb']??1)) : null;
    $name=trim($input['name']??'') ?: catBaseName($months);
    $serviceName=trim((string)($input['service_name'] ?? ''));
    $serviceType=adminNormalizeServiceType((string)($input['service_type']??'openvpn_l2tp'), $serviceName.' '.$name);
    $serviceName=adminServiceDefaultName($serviceType, $serviceName);
    $code=adminServicePrefix($serviceType).makeCatCode($months,$trafficType,$gb);
    $display=$months*1000 + ($trafficType==='limited' ? (int)$gb : 0);
    $st=$pdo->prepare("INSERT INTO plan_categories(code,service_type,service_name,name,months,traffic_type,traffic_limit_gb,is_active,display_order) VALUES(?,?,?,?,?,?,?,1,?) ON DUPLICATE KEY UPDATE service_type=VALUES(service_type), service_name=VALUES(service_name), name=VALUES(name), months=VALUES(months), traffic_type=VALUES(traffic_type), traffic_limit_gb=VALUES(traffic_limit_gb), is_active=1, deleted_at=NULL");
    $st->execute([$code,$serviceType,$serviceName,$name,$months,$trafficType,$gb,$display]);
    gemaccAdminActionNotify('دسته جدید پلن اضافه/فعال شد', ['کد دسته'=>$code, 'سرویس'=>$serviceName, 'مدت'=>$months.' ماه', 'نوع ترافیک'=>trafficLabel(['traffic_type'=>$trafficType,'traffic_limit_gb'=>$gb])], $userId);
    echo json_encode(['ok'=>true,'message'=>'دسته پلن اضافه شد','code'=>$code], JSON_UNESCAPED_UNICODE); exit;
}
if ($a==='delete_category') { $id=(int)($input['category_id']??0); $pdo->prepare("UPDATE plan_categories SET deleted_at=NOW(), is_active=0 WHERE id=?")->execute([$id]); $pdo->prepare("UPDATE plans SET is_active=0, deleted_at=COALESCE(deleted_at,NOW()) WHERE category_id=?")->execute([$id]); gemaccAdminActionNotify('دسته پلن و پلن‌های آن از فروش خارج شدند', ['شناسه دسته'=>$id], $userId); echo json_encode(['ok'=>true,'message'=>'دسته و پلن‌های آن از فروش خارج شدند'], JSON_UNESCAPED_UNICODE); exit; }
if ($a==='toggle_category') { $id=(int)($input['category_id']??0); $pdo->prepare("UPDATE plan_categories SET is_active=1-is_active WHERE id=?")->execute([$id]); gemaccAdminActionNotify('وضعیت دسته پلن تغییر کرد', ['شناسه دسته'=>$id], $userId); echo json_encode(['ok'=>true], JSON_UNESCAPED_UNICODE); exit; }
if ($a==='update_price') { $id=(int)($input['plan_id']??0); $price=(int)($input['price']??0); $pdo->prepare("UPDATE plans SET price=?, updated_at=NOW() WHERE id=?")->execute([$price,$id]); gemaccAdminActionNotify('قیمت فروش پلن تغییر کرد', ['شناسه پلن'=>$id, 'قیمت جدید'=>money($price)], $userId); echo json_encode(['ok'=>true], JSON_UNESCAPED_UNICODE); exit; }
if ($a==='update_purchase_price_per_user') { $unit=max(0,(int)preg_replace('/[^0-9]/','',(string)($input['purchase_price_per_user']??0))); $pdo->prepare("UPDATE plans SET purchase_price=GREATEST(1,COALESCE(user_count,seats,1))*?, updated_at=NOW() WHERE deleted_at IS NULL")->execute([$unit]); if(function_exists('setSetting')) setSetting('global_purchase_price_per_user',(string)$unit); gemaccAdminActionNotify('قیمت خرید همه پلن‌ها بر اساس هر کاربر ذخیره شد', ['قیمت خرید هر کاربر'=>money($unit)], $userId); echo json_encode(['ok'=>true,'message'=>'قیمت خرید همه پلن‌ها بر اساس تعداد کاربر ذخیره شد'], JSON_UNESCAPED_UNICODE); exit; }
if ($a==='update_windscribe_purchase_price_per_user') { $unit=max(0,(int)preg_replace('/[^0-9]/','',(string)($input['purchase_price_per_user']??0))); $pdo->prepare("UPDATE plans p JOIN plan_categories pc ON pc.id=p.category_id SET p.purchase_price=GREATEST(1,COALESCE(p.user_count,p.seats,1))*?, p.updated_at=NOW() WHERE p.deleted_at IS NULL AND pc.service_type='windscribe'")->execute([$unit]); if(function_exists('setSetting')) setSetting('windscribe_purchase_price_per_user',(string)$unit); gemaccAdminActionNotify('قیمت خرید Windscribe بروزرسانی شد', ['قیمت خرید هر کاربر'=>money($unit)], $userId); echo json_encode(['ok'=>true,'message'=>'قیمت خرید پلن‌های Windscribe بروزرسانی شد'], JSON_UNESCAPED_UNICODE); exit; }


if ($a==='update_service_purchase_profile') {
    $service=strtolower(trim((string)($input['service_type']??'')));
    $monthsProvided = isset($input['months']) && trim((string)$input['months']) !== '';
    $months=max(1,(int)($input['months']??1));
    $total=max(0,(int)preg_replace('/[^0-9]/','',(string)($input['total_purchase_price']??0)));
    $seats=max(1,(int)($input['purchase_seats']??$input['sale_seats']??1));
    $unit=max(0,(int)ceil($total/max(1,$seats)));
    if ($service==='openvpn_l2tp') { $unit=max(0,(int)preg_replace('/[^0-9]/','',(string)($input['purchase_price_per_user']??$total))); }
    if (!in_array($service, ['windscribe','expressvpn','v2ray','openvpn_l2tp'], true)) { echo json_encode(['ok'=>false,'error'=>'سرویس نامعتبر است'], JSON_UNESCAPED_UNICODE); exit; }
    $bucket = $months>=12 ? '_year' : '_month';
    if ($service==='openvpn_l2tp') {
        $pdo->prepare("UPDATE plans SET purchase_price=GREATEST(1,COALESCE(user_count,seats,1))*?, updated_at=NOW() WHERE deleted_at IS NULL AND (COALESCE(protocol,'openvpn_l2tp')='openvpn_l2tp' OR protocol IS NULL OR protocol='')")->execute([$unit]);
        setSetting('openvpn_purchase_price_per_user',(string)$unit);
        setSetting('openvpn_l2tp'.$bucket.'_purchase_total',(string)($total ?: $unit));
        setSetting('openvpn_l2tp'.$bucket.'_purchase_seats',(string)$seats);
        setSetting('openvpn_l2tp'.$bucket.'_sale_seats',(string)$seats);
        setSetting('openvpn'.$bucket.'_purchase_seats',(string)$seats);
        setSetting('openvpn'.$bucket.'_sale_seats',(string)$seats);
    } else {
        if ($service === 'v2ray' && !$monthsProvided) {
            $pdo->prepare("UPDATE plans p JOIN plan_categories pc ON pc.id=p.category_id SET p.purchase_price=?, p.seats=1, p.user_count=1, p.updated_at=NOW() WHERE p.deleted_at IS NULL AND pc.service_type='v2ray'")->execute([$unit]);
            setSetting('v2ray_purchase_price_per_config',(string)$unit);
        } else {
            $pdo->prepare("UPDATE plans p JOIN plan_categories pc ON pc.id=p.category_id SET p.purchase_price=GREATEST(1,COALESCE(p.user_count,p.seats,1))*?, p.updated_at=NOW() WHERE p.deleted_at IS NULL AND pc.service_type=? AND COALESCE(pc.months,p.months,1)=?")->execute([$unit,$service,$months]);
        }
        setSetting($service.$bucket.'_purchase_total',(string)$total);
        setSetting($service.$bucket.'_purchase_seats',(string)$seats);
        setSetting($service.$bucket.'_sale_seats',(string)$seats);
        if ($service === 'expressvpn') {
            setSetting('express'.$bucket.'_purchase_total',(string)$total);
            setSetting('express'.$bucket.'_purchase_seats',(string)$seats);
            setSetting('express'.$bucket.'_sale_seats',(string)$seats);
        }
    }
    $periodLabel = ($service === 'v2ray' && !$monthsProvided) ? 'همه پلن‌های V2Ray' : ($months.' ماه');
    gemaccAdminActionNotify('قیمت خرید/ظرفیت قیمت یکتای سرویس ذخیره شد', ['سرویس'=>$service, 'مدت'=>$periodLabel, 'قیمت کل خرید'=>money($total), 'ظرفیت'=>$seats, 'قیمت خرید هر کاربر/کانفیگ'=>money($unit)], $userId);
    echo json_encode(['ok'=>true,'message'=>'قیمت خرید/ظرفیت قیمت یکتای سرویس ذخیره شد','unit_price'=>$unit,'unit_sale_divisor'=>$seats], JSON_UNESCAPED_UNICODE); exit;
}

if ($a==='update_purchase_price') { $id=(int)($input['plan_id']??0); $cost=max(0,(int)preg_replace('/[^0-9]/','',(string)($input['purchase_price']??0))); $pdo->prepare("UPDATE plans SET purchase_price=?, updated_at=NOW() WHERE id=?")->execute([$cost,$id]); gemaccAdminActionNotify('قیمت خرید پلن ذخیره شد', ['شناسه پلن'=>$id, 'قیمت خرید'=>money($cost)], $userId); echo json_encode(['ok'=>true,'message'=>'قیمت خرید پلن ذخیره شد'], JSON_UNESCAPED_UNICODE); exit; }
if ($a==='add') {
    $catId=(int)($input['category_id']??0); $price=(int)($input['price']??0); $purchasePrice=max(0,(int)preg_replace('/[^0-9]/','',(string)($input['purchase_price']??0))); $title=trim($input['title']??''); $users=max(1,(int)($input['user_count']??$input['seats']??1));
    $st=$pdo->prepare("SELECT * FROM plan_categories WHERE id=? AND deleted_at IS NULL"); $st->execute([$catId]); $cat=$st->fetch(PDO::FETCH_ASSOC); if(!$cat){ echo json_encode(['ok'=>false,'error'=>'دسته انتخاب نشده'], JSON_UNESCAPED_UNICODE); exit; }
    $trafficType=$cat['traffic_type'] ?: 'unlimited'; $gb=$trafficType==='limited' ? (int)$cat['traffic_limit_gb'] : null;
    $serviceType=adminNormalizeServiceType((string)($cat['service_type']??'openvpn_l2tp'), (string)(($cat['service_name']??'').' '.($cat['name']??'').' '.$title));
    if ($serviceType === 'v2ray') $users = 1;
    $serviceName=adminServiceDefaultName($serviceType, (string)($cat['service_name'] ?? ''));
    if(!$title) $title=$serviceType==='windscribe' ? ('اشتراک اورجینال '.$serviceName.' '.$cat['name'].' | '.$users.' کاربر') : ($serviceType==='expressvpn' ? ('اشتراک '.$serviceName.' '.$cat['name'].' | '.$users.' کاربر') : ('سرویس '.$cat['name'].' - '.trafficLabel($cat).' '.$serviceName)); 
    $code=adminServicePrefix($serviceType).$cat['code'].'_'.$users.'_'.time();
    $st=$pdo->prepare("INSERT INTO plans(category_id,code,title,duration,months,seats,user_count,protocol,service_name,traffic_type,traffic_limit_gb,price,purchase_price,is_active,display_order) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,1,0)");
    $st->execute([$catId,$code,$title,$cat['code'],(int)$cat['months'],$users,$users,$serviceType,$serviceName,$trafficType,$gb,$price,$purchasePrice]);
    gemaccAdminActionNotify('پلن فروش جدید اضافه شد', ['عنوان'=>$title, 'سرویس'=>$serviceName, 'دسته'=>$cat['name'] ?? $cat['code'], 'تعداد کاربر'=>$users, 'قیمت فروش'=>money($price), 'قیمت خرید'=>money($purchasePrice)], $userId);
    echo json_encode(['ok'=>true,'message'=>'پلن فروش اضافه شد'], JSON_UNESCAPED_UNICODE); exit;
}
if ($a==='toggle') { echo json_encode(['ok'=>false,'error'=>'دکمه خاموش/روشن پلن حذف شده است؛ برای حذف از دکمه حذف استفاده کنید.'], JSON_UNESCAPED_UNICODE); exit; }
if ($a==='delete') { $id=(int)($input['plan_id']??0); $st=$pdo->prepare("SELECT id FROM orders WHERE plan_id=? LIMIT 1"); $st->execute([$id]); if($st->fetch()){ $pdo->prepare("UPDATE plans SET is_active=0, deleted_at=NOW() WHERE id=?")->execute([$id]); gemaccAdminActionNotify('پلن دارای سابقه سفارش از فروش خارج شد', ['شناسه پلن'=>$id], $userId); echo json_encode(['ok'=>true,'message'=>'پلن سابقه سفارش دارد و از فروش خارج شد'], JSON_UNESCAPED_UNICODE); exit;} $pdo->prepare("DELETE FROM plans WHERE id=?")->execute([$id]); gemaccAdminActionNotify('پلن فروش حذف شد', ['شناسه پلن'=>$id], $userId); echo json_encode(['ok'=>true], JSON_UNESCAPED_UNICODE); exit; }
echo json_encode(['ok'=>false,'error'=>'Invalid action'], JSON_UNESCAPED_UNICODE);
