<?php
if (!defined('AYCORE_SKIP_BOTAPI_ROUTER')) define('AYCORE_SKIP_BOTAPI_ROUTER', true);
session_start();
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../x-ui_single.php';
require_once __DIR__ . '/lib/icons.php';
require_once __DIR__ . '/lib/schema.php';
aycore_schema_ready($pdo);

$q = $pdo->prepare('SELECT * FROM admin WHERE username=:username LIMIT 1');
$q->execute([':username'=>$_SESSION['user'] ?? '']);
if (!isset($_SESSION['user']) || !$q->fetch(PDO::FETCH_ASSOC)) { header('Location: login.php'); exit; }
if (empty($_SESSION['csrf_token'])) $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
$csrf = $_SESSION['csrf_token'];
$flash = ['ok'=>'','err'=>''];
$xuiToolResult = null;
$xuiToolMeta = null;

function itz_xui_mode(array $p): string {
    $m = strtolower(trim((string)($p['xui_mode'] ?? '')));
    if (in_array($m,['modern','legacy'],true)) return $m;
    return trim((string)($p['xui_api_token'] ?? '')) !== '' ? 'modern' : 'legacy';
}
function itz_xui_snapshot(array $p): array {
    $d = json_decode((string)($p['xui_inbound_snapshot'] ?? ''), true);
    return is_array($d) ? $d : [];
}
function itz_xui_panel(PDO $pdo, int $id): ?array {
    $q=$pdo->prepare("SELECT * FROM marzban_panel WHERE id=:id AND type='x-ui_single' LIMIT 1");
    $q->execute([':id'=>$id]);
    $r=$q->fetch(PDO::FETCH_ASSOC); return $r ?: null;
}
function itz_xui_live(array $p): array {
    if (itz_xui_mode($p) !== 'modern') return ['ok'=>false,'items'=>[],'message'=>'این پنل Legacy است.'];
    $token=trim((string)($p['xui_api_token'] ?? ''));
    if ($token==='') return ['ok'=>false,'items'=>[],'message'=>'API Token ذخیره نشده است.'];
    return xui_token_fetch_inbounds_url((string)$p['url_panel'],$token,9);
}
function itz_xui_store_snapshot(PDO $pdo,int $id,array $items): void {
    $pdo->prepare("UPDATE marzban_panel SET xui_inbound_snapshot=:s,xui_last_sync=:t WHERE id=:id")
        ->execute([':s'=>xui_inbound_snapshot_payload($items),':t'=>time(),':id'=>$id]);
}

function itz_xui_redact($value) {
    if(!is_array($value)) return $value;
    $out=[];foreach($value as $k=>$v){$key=strtolower((string)$k);if(preg_match('/(^|_)(password|secret|token|api[_-]?key)(_|$)/i',$key))$out[$k]=(is_scalar($v)&&(string)$v!=='')?'••••REDACTED••••':$v;else$out[$k]=is_array($v)?itz_xui_redact($v):$v;}return $out;
}
function itz_xui_same_subscription_host(array $p,string $url): bool {
    $h=strtolower((string)parse_url($url,PHP_URL_HOST));if($h==='')return false;
    $allowed=[];foreach(['url_panel','linksubx'] as $key){$ah=strtolower((string)parse_url((string)($p[$key]??''),PHP_URL_HOST));if($ah!=='')$allowed[]=$ah;}
    return in_array($h,array_values(array_unique($allowed)),true);
}

if ($_SERVER['REQUEST_METHOD']==='POST') {
    if (!hash_equals($csrf,(string)($_POST['_csrf']??''))) { http_response_code(403); exit('درخواست معتبر نیست.'); }
    $action=(string)($_POST['_action']??''); $id=(int)($_POST['id']??0);
    if ($action==='bulk_sync') {
        $ok=0;$bad=0;$messages=[];
        try { $rows=$pdo->query("SELECT * FROM marzban_panel WHERE type='x-ui_single' AND COALESCE(xui_api_token,'')<>'' ORDER BY id")->fetchAll(PDO::FETCH_ASSOC)?:[]; } catch(Throwable $e){$rows=[];$messages[]=$e->getMessage();}
        foreach($rows as $row){
            try{$live=itz_xui_live($row);if(empty($live['ok']))throw new RuntimeException((string)($live['message']??'Sync failed'));$items=(array)($live['items']??[]);itz_xui_store_snapshot($pdo,(int)$row['id'],$items);
                if((string)($row['xui_auto_inbounds']??'0')==='1'){ $active=[];foreach($items as $it)if(!empty($it['enable'])&&(int)($it['id']??0)>0)$active[]=(int)$it['id'];if($active)$pdo->prepare('UPDATE marzban_panel SET inboundid=:i WHERE id=:id')->execute([':i'=>implode(',',array_values(array_unique($active))),':id'=>(int)$row['id']]);}
                $ok++;
            }catch(Throwable $e){$bad++;$messages[]=($row['name_panel']??('#'.$row['id'])).': '.$e->getMessage();}
        }
        $flash[$bad?'err':'ok']='Bulk Sync تمام شد؛ موفق: '.$ok.'، خطا: '.$bad.($messages?' — '.implode(' | ',array_slice($messages,0,3)):'');
        $p=null;
    } elseif ($action==='repair_inbounds') {
        $p=$id>0 ? itz_xui_panel($pdo,$id) : null;
        if(!$p || itz_xui_mode($p)!=='modern') $flash['err']='Repair فقط برای پنل Modern قابل اجراست.';
        else { try { $live=itz_xui_live($p);if(empty($live['ok']))throw new RuntimeException((string)($live['message']??'Sync failed'));$items=(array)($live['items']??[]);itz_xui_store_snapshot($pdo,$id,$items);$active=[];foreach($items as $it)if(!empty($it['enable'])&&(int)($it['id']??0)>0)$active[]=(int)$it['id'];$active=array_values(array_unique($active));$selected=xui_parse_inbound_ids($p['inboundid']??'');$valid=array_values(array_intersect($selected,$active));if(!$valid&&$active)$valid=[reset($active)];if(!$valid)throw new RuntimeException('هیچ Inbound فعالی برای Repair پیدا نشد.');$pdo->prepare('UPDATE marzban_panel SET inboundid=:i WHERE id=:id')->execute([':i'=>implode(',',$valid),':id'=>$id]);$flash['ok']='Inboundهای نامعتبر حذف و انتخاب سالم ذخیره شد.';} catch(Throwable $e){$flash['err']=$e->getMessage();} }
    } else {
    $p=$id>0 ? itz_xui_panel($pdo,$id) : null;
    if (!$p) $flash['err']='پنل ثنایی پیدا نشد.';
    elseif (itz_xui_mode($p)==='legacy') {
        if ($action === 'legacy_test') {
            try {
                $r = login((string)($p['code_panel'] ?? ''), false);
                if (!empty($r['success'])) $flash['ok']='اتصال Legacy با Username/Password برقرار است.';
                else $flash['err']='اتصال Legacy برقرار نشد؛ آدرس، Username/Password و دسترسی پنل را بررسی کن.';
            } catch (Throwable $e) { $flash['err']='تست Legacy ناموفق بود: '.$e->getMessage(); }
        } else {
            $flash['err']='این عملیات مخصوص ثنایی جدید / Token Mode است. پنل Legacy در بخش خودش مدیریت می‌شود.';
        }
    } else {
        try {
            if ($action==='test') {
                $r=xui_test_api_token_url((string)$p['url_panel'],(string)$p['xui_api_token'],9);
                if (!empty($r['verified'])) $flash['ok']='اتصال Token تایید شد؛ 3x-ui 3.6.x آماده پاسخ‌گویی است.';
                else $flash['err']=(string)($r['message']??'تست اتصال ناموفق بود.');
            } elseif ($action==='update_token') {
                $newToken=trim((string)($_POST['new_xui_token']??''));
                if ($newToken==='') throw new RuntimeException('Token جدید خالی است.');
                $test=xui_test_api_token_url((string)$p['url_panel'],$newToken,9);
                if (empty($test['verified'])) throw new RuntimeException('Token ذخیره نشد: '.(string)($test['message']??'تست اتصال ناموفق بود.'));
                $pdo->prepare("UPDATE marzban_panel SET xui_api_token=:t,xui_mode='modern',username_panel='',password_panel='',api_key=NULL,datelogin=NULL WHERE id=:id")
                    ->execute([':t'=>$newToken,':id'=>$id]);
                $fresh=itz_xui_panel($pdo,$id);
                $live=$fresh ? itz_xui_live($fresh) : ['ok'=>false];
                if (!empty($live['ok'])) itz_xui_store_snapshot($pdo,$id,(array)($live['items']??[]));
                $flash['ok']='API Token تست و جایگزین شد؛ credentialهای Legacy برای این پروفایل خالی ماندند.';
            } elseif ($action==='xui_tg_lookup') {
                $tg=trim((string)($_POST['tg_id']??''));$r=xui_token_clients_by_tgid($p,$tg,9);
                if(empty($r['ok']))throw new RuntimeException((string)($r['message']??'Telegram ID lookup failed'));
                $xuiToolMeta='Telegram ID '.$tg;$xuiToolResult=['clients'=>$r['items']??[],'count'=>count((array)($r['items']??[]))];$flash['ok']='جستجوی Telegram ID انجام شد؛ '.count((array)($r['items']??[])).' کلاینت پیدا شد.';
            } elseif ($action==='xui_openapi_sync') {
                $r=xui_token_openapi($p,10);if(empty($r['ok']))throw new RuntimeException((string)($r['message']??'OpenAPI دریافت نشد.'));
                $ops=xui_token_openapi_operations((array)$r['spec']);$tags=[];foreach($ops as $op){$tag=(string)($op['tags'][0]??'Other');$tags[$tag]=($tags[$tag]??0)+1;}arsort($tags);
                $xuiToolMeta='3x-ui v3.6 OpenAPI';$xuiToolResult=['operations'=>count($ops),'tags'=>$tags,'sample'=>array_slice($ops,0,80)];$flash['ok']='OpenAPI احراز‌شده دریافت شد؛ '.count($ops).' عملیات کشف شد.';
            } elseif ($action==='xui_api_call') {
                $method=strtoupper(trim((string)($_POST['api_method']??'GET')));$path=trim((string)($_POST['api_path']??''));
                if(strpos($path,'http://')===0||strpos($path,'https://')===0||strpos($path,'..')!==false)throw new RuntimeException('فقط مسیر داخلی /panel/api/... مجاز است.');
                $oa=xui_token_openapi($p,10);if(empty($oa['ok']))throw new RuntimeException('OpenAPI احراز‌شده در دسترس نیست.');$match=xui_token_openapi_match((array)$oa['spec'],$method,$path);if(!$match)throw new RuntimeException('این Method/Path در OpenAPI همین نسخه 3x-ui وجود ندارد.');
                if(in_array($method,['POST','PUT','PATCH','DELETE'],true)&&empty($_POST['confirm_mutation']))throw new RuntimeException('برای عملیات تغییردهنده تیک تأیید را فعال کن.');
                $payload=null;if(in_array($method,['POST','PUT','PATCH'],true)){$raw=trim((string)($_POST['api_payload']??''));$payload=$raw===''?[]:json_decode($raw,true);if(!is_array($payload))throw new RuntimeException('Payload باید JSON معتبر باشد.');}
                $resp=xui_api_token_request($p,$method,$path,$payload,10);$status=(int)($resp['status']??0);$decoded=xui_token_decode($resp);$body=is_array($decoded)?$decoded:(string)($resp['body']??'');$xuiToolMeta=$method.' '.($match['path']??$path);$xuiToolResult=['http'=>$status,'body'=>itz_xui_redact($body),'error'=>$resp['error']??null];if($status<200||$status>=300)throw new RuntimeException((string)($resp['error']??('HTTP '.$status)));$flash['ok']='OpenAPI operation اجرا شد.';
            } elseif ($action==='xui_set_reset_day') {
                $iid=(int)($_POST['reset_inbound_id']??0);$day=(int)($_POST['reset_day']??0);
                $r=xui_token_set_monthly_reset_day($p,$iid,$day,10);if(empty($r['ok']))throw new RuntimeException((string)($r['message']??'Monthly reset update failed'));
                // Refresh snapshot after changing inbound-level reset policy.
                $live=itz_xui_live($p);if(!empty($live['ok']))itz_xui_store_snapshot($pdo,$id,(array)($live['items']??[]));
                $xuiToolMeta='Monthly reset · Inbound #'.$iid;$xuiToolResult=['trafficReset'=>'monthly','trafficResetDay'=>$day];$flash['ok']='روز Reset ماهانه Inbound #'.$iid.' روی '.$day.' ذخیره شد.';
            } elseif ($action==='xui_sub_info') {
                $url=trim((string)($_POST['subscription_url']??''));if(!filter_var($url,FILTER_VALIDATE_URL))throw new RuntimeException('Subscription URL معتبر نیست.');if(!itz_xui_same_subscription_host($p,$url))throw new RuntimeException('برای جلوگیری از درخواست به مقصد دلخواه، دامنه Subscription باید با دامنه پنل/ساب ذخیره‌شده یکی باشد.');
                $r=xui_subscription_info($url,10);if(empty($r['ok']))throw new RuntimeException((string)($r['message']??'Subscription info failed'));$xuiToolMeta='Subscription ?format=info';$xuiToolResult=$r['info'];$flash['ok']='Live subscription info دریافت شد.';
            } elseif ($action==='xui_sub_raw') {
                $url=trim((string)($_POST['subscription_url']??''));if(!filter_var($url,FILTER_VALIDATE_URL))throw new RuntimeException('Subscription URL معتبر نیست.');if(!itz_xui_same_subscription_host($p,$url))throw new RuntimeException('برای جلوگیری از درخواست به مقصد دلخواه، دامنه Subscription باید با دامنه پنل/ساب ذخیره‌شده یکی باشد.');
                $r=xui_subscription_raw($url,10);if(empty($r['ok']))throw new RuntimeException((string)($r['message']??'Raw subscription download failed'));$body=(string)($r['body']??'');$xuiToolMeta='Raw subscription download';$xuiToolResult=['bytes'=>strlen($body),'preview'=>mb_substr($body,0,20000,'UTF-8'),'truncated'=>strlen($body)>20000];$flash['ok']='Raw subscription دریافت شد'.(strlen($body)>20000?'؛ پیش‌نمایش برای ایمنی کوتاه شده است.':'.');
            } elseif ($action==='xui_sub_format') {
                $url=trim((string)($_POST['subscription_url']??''));$format=trim((string)($_POST['subscription_format']??''));if(!filter_var($url,FILTER_VALIDATE_URL))throw new RuntimeException('Subscription URL معتبر نیست.');if(!itz_xui_same_subscription_host($p,$url))throw new RuntimeException('دامنه Subscription باید با دامنه پنل/ساب ذخیره‌شده یکی باشد.');
                $r=xui_subscription_format($url,$format,10);if(empty($r['ok']))throw new RuntimeException((string)($r['message']??'Format probe failed'));$body=(string)($r['body']??'');$xuiToolMeta='Subscription format='.$format;$xuiToolResult=['format'=>$format,'bytes'=>strlen($body),'preview'=>mb_substr($body,0,20000,'UTF-8'),'truncated'=>strlen($body)>20000];$flash['ok']='خروجی format='.$format.' دریافت شد.';
            } elseif ($action==='xui_sub_ua') {
                $url=trim((string)($_POST['subscription_url']??''));$ua=trim((string)($_POST['subscription_user_agent']??''));if(!filter_var($url,FILTER_VALIDATE_URL))throw new RuntimeException('Subscription URL معتبر نیست.');if(!itz_xui_same_subscription_host($p,$url))throw new RuntimeException('دامنه Subscription باید با دامنه پنل/ساب ذخیره‌شده یکی باشد.');
                $r=xui_subscription_user_agent_probe($url,$ua,10);if(empty($r['ok']))throw new RuntimeException((string)($r['message']??'User-Agent probe failed'));$body=(string)($r['body']??'');$xuiToolMeta='Subscription User-Agent auto-detect';$xuiToolResult=['user_agent'=>$ua,'bytes'=>strlen($body),'preview'=>mb_substr($body,0,20000,'UTF-8'),'truncated'=>strlen($body)>20000];$flash['ok']='تست auto-detect بر اساس User-Agent انجام شد.';
            } elseif ($action==='sync' || $action==='save_inbounds') {
                $live=itz_xui_live($p);
                if (empty($live['ok'])) throw new RuntimeException('Sync ناموفق: '.(string)($live['message']??'خطای نامشخص'));
                $items=(array)($live['items']??[]); itz_xui_store_snapshot($pdo,$id,$items);
                if ($action==='sync') {
                    $flash['ok']=count($items).' Inbound از 3x-ui همگام شد.';
                } else {
                    $active=[];
                    foreach ($items as $it) if (!empty($it['enable']) && (int)($it['id']??0)>0) $active[]=(int)$it['id'];
                    $active=array_values(array_unique($active));
                    $auto=!empty($_POST['xui_auto_inbounds']) ? '1':'0';
                    if ($auto==='1') $chosen=$active;
                    else {
                        $chosen=[];
                        foreach ((array)($_POST['inbounds']??[]) as $v) { $n=(int)$v; if ($n>0 && in_array($n,$active,true)) $chosen[]=$n; }
                        $chosen=array_values(array_unique($chosen));
                    }
                    if (!$chosen) throw new RuntimeException('حداقل یک Inbound فعال انتخاب کن.');
                    $pdo->prepare("UPDATE marzban_panel SET inboundid=:i,xui_auto_inbounds=:a WHERE id=:id")
                        ->execute([':i'=>implode(',',$chosen),':a'=>$auto,':id'=>$id]);
                    $flash['ok']='تنظیم Inbound ذخیره شد'.($auto==='1'?'؛ Auto-Inbound فعال است.':'.');
                }
            }
        } catch (Throwable $e) { $flash['err']=$e->getMessage(); error_log('[xui hub] '.$e->getMessage()); }
    }
    }
}

$all=[];
try { $all=$pdo->query("SELECT * FROM marzban_panel WHERE type='x-ui_single' ORDER BY id DESC")->fetchAll(PDO::FETCH_ASSOC) ?: []; } catch(Throwable $e){$flash['err']=$e->getMessage();}
$modern=[];$legacy=[];
foreach($all as $p){ if(itz_xui_mode($p)==='modern')$modern[]=$p;else$legacy[]=$p; }
$focus=(int)($_GET['panel']??0);
?>
<!doctype html><html lang="fa" dir="rtl"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>iTz 3x-ui Hub | iTzAYDiN-BOT</title>
<link rel="stylesheet" href="css/theme.css"><link rel="stylesheet" href="css/admin-extra.css"><link rel="stylesheet" href="css/ay-controls.css">
<script src="js/theme.js" defer></script>
<style>
.xhub-hero{display:flex;justify-content:space-between;gap:18px;align-items:center;padding:22px;border:1px solid var(--border-soft);border-radius:22px;background:linear-gradient(135deg,var(--surface-2),rgba(124,92,255,.09));margin-bottom:18px}.xhub-kicker{font:700 11px 'JetBrains Mono',monospace;letter-spacing:2px;color:var(--accent)}.xhub-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px}.xhub-card{border:1px solid var(--border-soft);border-radius:18px;background:var(--surface-2);padding:16px}.xhub-card.focus{outline:2px solid var(--accent);outline-offset:2px}.xhub-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:12px}.xhub-head h3{margin:0 0 4px}.xhub-meta{font-size:12px;color:var(--text-muted);direction:ltr;text-align:right}.xhub-inbounds{display:grid;gap:7px;margin:12px 0}.xhub-inbound{display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:center;padding:9px 10px;border:1px solid var(--border-soft);border-radius:12px;background:var(--surface-3)}.xhub-inbound.off{opacity:.48}.xhub-inbound small{display:block;color:var(--text-muted);font-size:11px}.xhub-id{font-family:'JetBrains Mono',monospace;color:var(--accent)}.xhub-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}.xhub-auto{display:flex;align-items:center;gap:8px;padding:10px;border-radius:12px;background:var(--accent-soft);margin-top:10px}.xhub-section-title{display:flex;justify-content:space-between;align-items:center;margin:24px 0 10px}.xhub-section-title h2{font-size:17px;margin:0}.xhub-empty{padding:28px;text-align:center;color:var(--text-muted);border:1px dashed var(--border-mid);border-radius:16px}.xhub-stats{display:flex;gap:8px;flex-wrap:wrap}.xhub-stat{padding:7px 10px;border-radius:999px;background:var(--surface-3);font-size:12px}.xhub-legacy{border-style:dashed}.xhub-legacy .xhub-actions{margin-top:14px}@media(max-width:640px){.xhub-hero{align-items:flex-start;flex-direction:column}.xhub-grid{grid-template-columns:1fr}}
</style></head><body><section id="container"><?php include 'header.php'; ?><section id="main-content"><div class="wrapper">
<div class="xhub-hero"><div><div class="xhub-kicker">iTz • 3X-UI CONTROL FABRIC</div><h1 style="margin:6px 0">ثنایی جدید و قدیمی، کاملاً جدا</h1><p style="margin:0;color:var(--text-muted)">Modern 3.6.x با API Token، OpenAPI احراز‌شده و Inbound Sync؛ Legacy فقط با Username/Password. هیچ credential مشترکی بین این دو پروفایل استفاده نمی‌شود.</p></div><div class="xhub-stats"><span class="xhub-stat">Modern: <?php echo count($modern); ?></span><span class="xhub-stat">Legacy: <?php echo count($legacy); ?></span><a class="btn btn-primary btn-sm" href="panels.php">+ افزودن پنل</a><form method="post" style="display:inline"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><button class="btn btn-outline btn-sm" name="_action" value="bulk_sync">↻ Bulk Sync همه Modern</button></form></div></div>
<?php if($flash['ok']):?><div class="alert alert-success"><?php echo htmlspecialchars($flash['ok'],ENT_QUOTES,'UTF-8');?></div><?php endif;?>
<?php if($flash['err']):?><div class="alert alert-danger"><?php echo htmlspecialchars($flash['err'],ENT_QUOTES,'UTF-8');?></div><?php endif;?>
<div class="xhub-section-title"><h2>🆕 ثنایی جدید • 3.6.x Token Mode</h2><small style="color:var(--text-muted)">مدیریت Inbound برای ساخت اشتراک‌های جدید</small></div>
<?php if(!$modern):?><div class="xhub-empty">هنوز پنل Modern ثبت نشده. از «مدیریت پنل‌ها» ثنایی جدید را انتخاب کن.</div><?php else:?><div class="xhub-grid">
<?php foreach($modern as $p): $snapshot=itz_xui_snapshot($p);$selected=xui_parse_inbound_ids($p['inboundid']??'');$activeCount=0;foreach($snapshot as $it)if(!empty($it['enable']))$activeCount++;$last=(int)($p['xui_last_sync']??0);?>
<form method="post" class="xhub-card <?php echo $focus===(int)$p['id']?'focus':'';?>"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><input type="hidden" name="id" value="<?php echo (int)$p['id'];?>">
<div class="xhub-head"><div><h3><?php echo htmlspecialchars($p['name_panel']??'',ENT_QUOTES,'UTF-8');?></h3><div class="xhub-meta"><?php echo htmlspecialchars($p['url_panel']??'',ENT_QUOTES);?></div></div><span class="badge badge-active">TOKEN</span></div>
<div class="xhub-stats"><span class="xhub-stat"><?php echo count($snapshot);?> Inbound</span><span class="xhub-stat"><?php echo $activeCount;?> فعال</span><span class="xhub-stat"><?php echo ((string)($p['xui_auto_inbounds']??'0')==='1')?'AUTO ON':'AUTO OFF';?></span></div>
<?php $snapshotIds=[];$activeIds=[];foreach($snapshot as $it){$si=(int)($it['id']??0);if($si>0)$snapshotIds[]=$si;if($si>0&&!empty($it['enable']))$activeIds[]=$si;}$missing=array_values(array_diff($selected,$snapshotIds));$disabledSelected=array_values(array_diff(array_intersect($selected,$snapshotIds),$activeIds));?>
<?php if($missing||$disabledSelected):?><div class="alert alert-warning" style="margin:10px 0 0;font-size:12px">⚠️ انتخاب Inbound نیاز به Repair دارد<?php if($missing):?> · ID گم‌شده: <code><?php echo htmlspecialchars(implode(',',$missing),ENT_QUOTES);?></code><?php endif;?><?php if($disabledSelected):?> · خاموش: <code><?php echo htmlspecialchars(implode(',',$disabledSelected),ENT_QUOTES);?></code><?php endif;?></div><?php endif;?>
<?php if($last):?><div style="font-size:11px;color:var(--text-muted);margin-top:8px">آخرین Sync: <?php echo htmlspecialchars(date('Y-m-d H:i:s',$last),ENT_QUOTES);?></div><?php endif;?>
<div class="xhub-inbounds">
<?php if(!$snapshot):?><div style="font-size:12px;color:var(--text-muted)">برای دیدن Inboundها دکمه Sync را بزن.</div><?php endif;?>
<?php foreach($snapshot as $it):$iid=(int)($it['id']??0);$en=!empty($it['enable']);?><label class="xhub-inbound <?php echo $en?'':'off';?>"><input type="checkbox" name="inbounds[]" value="<?php echo $iid;?>" <?php echo in_array($iid,$selected,true)?'checked':'';?> <?php echo $en?'':'disabled';?>><span><b><?php echo htmlspecialchars(($it['remark']??'')?:('Inbound #'.$iid),ENT_QUOTES,'UTF-8');?></b><small><?php echo htmlspecialchars(strtoupper((string)($it['protocol']??'')),ENT_QUOTES);?> <?php echo !empty($it['port'])?':'.(int)$it['port']:'';?> · <?php echo $en?'فعال':'خاموش';?><?php $resetMode=trim((string)($it['trafficReset']??''));$resetDay=(int)($it['trafficResetDay']??0);if($resetMode!==''):?> · Reset: <?php echo htmlspecialchars($resetMode,ENT_QUOTES);?><?php echo $resetMode==='monthly'&&$resetDay>0?' @ day '.$resetDay:'';?><?php endif;?></small></span><span class="xhub-id">#<?php echo $iid;?></span></label><?php endforeach;?>
</div>
<label class="xhub-auto"><input type="checkbox" name="xui_auto_inbounds" value="1" <?php echo ((string)($p['xui_auto_inbounds']??'0')==='1')?'checked':'';?>><span><b>Auto-Inbound</b><small style="display:block;color:var(--text-muted)">همه Inboundهای فعالِ لحظه خرید برای کلاینت جدید انتخاب شوند.</small></span></label>
<div style="margin-top:12px"><label style="font-size:12px;color:var(--text-muted);display:block;margin-bottom:6px">تعویض API Token — مقدار فعلی هیچ‌وقت نمایش داده نمی‌شود</label><input class="form-control" type="password" name="new_xui_token" autocomplete="new-password" placeholder="Token جدید را فقط هنگام تعویض وارد کن" style="direction:ltr"></div>
<div class="xhub-actions"><button class="btn btn-primary btn-sm" name="_action" value="save_inbounds">ذخیره Inboundها</button><button class="btn btn-outline btn-sm" name="_action" value="sync">↻ Sync</button><button class="btn btn-outline btn-sm" name="_action" value="repair_inbounds">🧰 Repair Inbound</button><button class="btn btn-soft-purple btn-sm" name="_action" value="test">تست Token</button><button class="btn btn-outline btn-sm" name="_action" value="update_token">تعویض امن Token</button><a class="btn btn-outline btn-sm" href="panels.php?focus=<?php echo (int)$p['id'];?>">تنظیمات عمومی</a></div>
</form><?php endforeach;?></div><?php endif;?>
<div class="card" style="margin-top:18px"><div class="card__head"><div><div class="card__title">🧰 3x-ui 3.6 Toolkit</div><div style="font-size:12px;color:var(--text-muted)">Telegram-ID lookup، Custom Monthly Reset، OpenAPI احراز‌شده، Console پویا، ?format=info و Raw Subscription.</div></div><span class="chip">v3.6.0-ready</span></div>
<?php if($modern):?><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><div class="form-row"><div class="form-group"><label class="form-label">پنل Modern</label><select class="form-control" name="id"><?php foreach($modern as $mp):?><option value="<?php echo (int)$mp['id'];?>"><?php echo htmlspecialchars($mp['name_panel']??'',ENT_QUOTES,'UTF-8');?></option><?php endforeach;?></select></div><div class="form-group"><label class="form-label">Telegram ID</label><input class="form-control" name="tg_id" dir="ltr" placeholder="123456789"></div></div><div class="xhub-actions"><button class="btn btn-primary btn-sm" name="_action" value="xui_tg_lookup">جستجوی کلاینت با Telegram ID</button><button class="btn btn-outline btn-sm" name="_action" value="xui_openapi_sync">دریافت OpenAPI 3.6</button></div></form>
<hr style="border-color:var(--border-soft);margin:16px 0"><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><div class="form-row"><div class="form-group"><label class="form-label">پنل Modern</label><select class="form-control" name="id"><?php foreach($modern as $mp):?><option value="<?php echo (int)$mp['id'];?>"><?php echo htmlspecialchars($mp['name_panel']??'',ENT_QUOTES,'UTF-8');?></option><?php endforeach;?></select></div><div class="form-group"><label class="form-label">Method</label><select class="form-control" name="api_method"><option>GET</option><option>POST</option><option>PUT</option><option>PATCH</option><option>DELETE</option></select></div></div><div class="form-group"><label class="form-label">OpenAPI Path</label><input class="form-control" name="api_path" dir="ltr" placeholder="/panel/api/clients/list"></div><div class="form-group"><label class="form-label">JSON Payload</label><textarea class="form-control" name="api_payload" rows="4" dir="ltr" placeholder="{}"></textarea></div><label style="display:flex;gap:8px;align-items:center;margin:8px 0"><input type="checkbox" name="confirm_mutation" value="1"> اجرای POST/PUT/PATCH/DELETE را تأیید می‌کنم</label><button class="btn btn-outline btn-sm" name="_action" value="xui_api_call">اجرای endpoint موجود در OpenAPI</button></form>
<hr style="border-color:var(--border-soft);margin:16px 0"><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><div class="form-row"><div class="form-group"><label class="form-label">پنل Modern</label><select class="form-control" name="id"><?php foreach($modern as $mp):?><option value="<?php echo (int)$mp['id'];?>"><?php echo htmlspecialchars($mp['name_panel']??'',ENT_QUOTES,'UTF-8');?></option><?php endforeach;?></select></div><div class="form-group"><label class="form-label">Inbound ID</label><input class="form-control" type="number" min="1" name="reset_inbound_id" placeholder="1"></div><div class="form-group"><label class="form-label">روز Reset ماهانه</label><input class="form-control" type="number" min="1" max="31" name="reset_day" placeholder="15"></div></div><button class="btn btn-outline btn-sm" name="_action" value="xui_set_reset_day">تنظیم Custom Monthly Reset Day</button><div class="form-hint">قابلیت جدید 3x-ui 3.6.0؛ Traffic Reset همان Inbound روی monthly قرار می‌گیرد و روز 1 تا 31 ذخیره می‌شود.</div></form>
<hr style="border-color:var(--border-soft);margin:16px 0"><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><div class="form-row"><div class="form-group"><label class="form-label">پنل Modern</label><select class="form-control" name="id"><?php foreach($modern as $mp):?><option value="<?php echo (int)$mp['id'];?>"><?php echo htmlspecialchars($mp['name_panel']??'',ENT_QUOTES,'UTF-8');?></option><?php endforeach;?></select></div><div class="form-group"><label class="form-label">Subscription URL همان پنل</label><input class="form-control" name="subscription_url" dir="ltr" placeholder="https://panel.example/sub/..." type="url"></div></div><div class="xhub-actions"><button class="btn btn-outline btn-sm" name="_action" value="xui_sub_info">دریافت Live info (?format=info)</button><button class="btn btn-outline btn-sm" name="_action" value="xui_sub_raw">دریافت Raw Subscription</button></div></form>
<hr style="border-color:var(--border-soft);margin:16px 0"><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><div class="form-row"><div class="form-group"><label class="form-label">پنل Modern</label><select class="form-control" name="id"><?php foreach($modern as $mp):?><option value="<?php echo (int)$mp['id'];?>"><?php echo htmlspecialchars($mp['name_panel']??'',ENT_QUOTES,'UTF-8');?></option><?php endforeach;?></select></div><div class="form-group"><label class="form-label">Subscription URL</label><input class="form-control" name="subscription_url" dir="ltr" placeholder="https://panel.example/sub/..." type="url"></div></div><div class="form-row"><div class="form-group"><label class="form-label">format دلخواه</label><input class="form-control" name="subscription_format" dir="ltr" placeholder="مثلاً info یا فرمت پشتیبانی‌شده توسط همان نسخه"></div><div class="form-group"><label class="form-label">User-Agent برای Auto Detection</label><input class="form-control" name="subscription_user_agent" dir="ltr" maxlength="220" placeholder="نام کلاینت / User-Agent"></div></div><div class="xhub-actions"><button class="btn btn-outline btn-sm" name="_action" value="xui_sub_format">تست format دلخواه</button><button class="btn btn-outline btn-sm" name="_action" value="xui_sub_ua">تست User-Agent Auto-Detect</button></div><div class="form-hint">در 3x-ui 3.6.0 تشخیص فرمت از User-Agent اضافه شده؛ این ابزار بدون هاردکد کردن لیست فرمت‌ها، رفتار همان نسخه نصب‌شده را تست می‌کند.</div></form>
<?php else:?><div class="xhub-empty">برای Toolkit حداقل یک پنل Modern لازم است.</div><?php endif;?>
<?php if($xuiToolResult!==null):?><div style="margin-top:14px"><div class="xhub-stat"><?php echo htmlspecialchars((string)$xuiToolMeta,ENT_QUOTES,'UTF-8');?></div><pre style="direction:ltr;text-align:left;white-space:pre-wrap;overflow:auto;max-height:420px;background:#090b12;color:#d6daf0;padding:13px;border-radius:13px;font:12px/1.7 monospace"><?php echo htmlspecialchars(is_array($xuiToolResult)?json_encode($xuiToolResult,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT):(string)$xuiToolResult,ENT_QUOTES,'UTF-8');?></pre></div><?php endif;?></div>
<div class="xhub-section-title"><h2>🕰 ثنایی قدیمی • Legacy</h2><small style="color:var(--text-muted)">بدون Token و بدون API جدید</small></div>
<?php if(!$legacy):?><div class="xhub-empty">پنل Legacy ثبت نشده.</div><?php else:?><div class="xhub-grid"><?php foreach($legacy as $p):?><form method="post" class="xhub-card xhub-legacy"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><input type="hidden" name="id" value="<?php echo (int)$p['id'];?>"><div class="xhub-head"><div><h3><?php echo htmlspecialchars($p['name_panel']??'',ENT_QUOTES,'UTF-8');?></h3><div class="xhub-meta"><?php echo htmlspecialchars($p['url_panel']??'',ENT_QUOTES);?></div></div><span class="badge badge-info">LEGACY</span></div><div style="color:var(--text-muted);font-size:12px">Username: <code><?php echo htmlspecialchars($p['username_panel']??'—',ENT_QUOTES);?></code> · Inbound: <code><?php echo htmlspecialchars($p['inboundid']??'—',ENT_QUOTES);?></code></div><div style="margin-top:8px;font-size:11px;color:var(--text-muted)">Token و Auto-Inbound در این کارت عمداً وجود ندارند.</div><div class="xhub-actions"><button class="btn btn-outline btn-sm" name="_action" value="legacy_test">تست اتصال Legacy</button><a class="btn btn-outline btn-sm" href="panels.php?focus=<?php echo (int)$p['id'];?>">ویرایش Legacy</a></div></form><?php endforeach;?></div><?php endif;?>
</div></section></section></body></html>
