<?php
if (!defined('AYCORE_SKIP_BOTAPI_ROUTER')) define('AYCORE_SKIP_BOTAPI_ROUTER', true);
session_start();
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/lib/icons.php';
require_once __DIR__ . '/lib/schema.php';
if (!isset($pdo) || !($pdo instanceof PDO)) { http_response_code(503); exit('دیتابیس در دسترس نیست.'); }
aycore_schema_ready($pdo);
$q=$pdo->prepare('SELECT * FROM admin WHERE username=:u LIMIT 1');
$q->execute([':u'=>$_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'=>''];

try {
    $pdo->exec("CREATE TABLE IF NOT EXISTS itz_ops_history (
      id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
      admin_user VARCHAR(190) NULL,
      action_name VARCHAR(120) NOT NULL,
      status_name VARCHAR(30) NOT NULL DEFAULT 'ok',
      meta_json MEDIUMTEXT NULL,
      created_at INT UNSIGNED NOT NULL DEFAULT 0,
      PRIMARY KEY(id), KEY idx_created_at(created_at), KEY idx_action(action_name)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
} catch (Throwable $e) { error_log('[AY Ops schema] '.$e->getMessage()); }

function ay_ops_log(PDO $pdo,string $action,string $status='ok',array $meta=[]): void {
    try {
        foreach (['token','api_key','password','secret','key'] as $needle) {
            foreach ($meta as $k=>$v) if (stripos((string)$k,$needle)!==false) $meta[$k]='***';
        }
        $s=$pdo->prepare('INSERT INTO itz_ops_history(admin_user,action_name,status_name,meta_json,created_at) VALUES(:u,:a,:s,:m,:t)');
        $s->execute([':u'=>$_SESSION['user']??'admin',':a'=>$action,':s'=>$status,':m'=>json_encode($meta,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),':t'=>time()]);
    } catch (Throwable $e) {}
}
function ay_ops_table_exists(PDO $pdo,string $table): bool {
    try { $s=$pdo->prepare('SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name=:t');$s->execute([':t'=>$table]);return (int)$s->fetchColumn()>0; } catch(Throwable $e){return false;}
}
function ay_ops_count(PDO $pdo,string $table): ?int {
    if (!preg_match('/^[A-Za-z0-9_]+$/',$table) || !ay_ops_table_exists($pdo,$table)) return null;
    try { return (int)$pdo->query("SELECT COUNT(*) FROM `{$table}`")->fetchColumn(); } catch(Throwable $e){return null;}
}
function ay_ops_tg_call(string $token,string $method,array $params=[]): array {
    if ($token==='' || !function_exists('curl_init')) return ['ok'=>false,'description'=>$token===''?'Bot Token تنظیم نشده است.':'افزونه cURL روی PHP فعال نیست.'];
    $ch=curl_init('https://api.telegram.org/bot'.$token.'/'.$method);
    curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>$params,CURLOPT_CONNECTTIMEOUT=>7,CURLOPT_TIMEOUT=>15,CURLOPT_SSL_VERIFYPEER=>true,CURLOPT_SSL_VERIFYHOST=>2,CURLOPT_USERAGENT=>'iTzAYDiN-BOT/3 Ops']);
    $raw=curl_exec($ch);$err=curl_error($ch);$no=curl_errno($ch);$http=(int)curl_getinfo($ch,CURLINFO_HTTP_CODE);curl_close($ch);
    if ($raw===false) return ['ok'=>false,'description'=>'cURL #'.$no.': '.$err,'http'=>$http];
    $j=json_decode((string)$raw,true);if(!is_array($j))return ['ok'=>false,'description'=>'پاسخ Telegram JSON معتبر نبود.','http'=>$http];
    $j['_http']=$http;return $j;
}
function ay_ops_expected_webhook(): string {
    $d=trim((string)($GLOBALS['domainhosts']??''));
    if ($d==='') return '';
    if (!preg_match('#^https?://#i',$d)) $d='https://'.$d;
    return rtrim($d,'/').'/index.php';
}
function ay_ops_setting(PDO $pdo,string $column,string $default=''): string {
    if (!preg_match('/^[A-Za-z0-9_]+$/',$column)) return $default;
    try { $v=$pdo->query("SELECT `{$column}` FROM setting LIMIT 1")->fetchColumn(); return $v===false?$default:(string)$v; } catch(Throwable $e){return $default;}
}
function ay_ops_download(string $name,array $payload): never {
    if (!headers_sent()) {
        header('Content-Type: application/json; charset=utf-8');
        header('Content-Disposition: attachment; filename="'.$name.'"');
        header('Cache-Control: no-store, max-age=0');
    }
    echo json_encode($payload,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);exit;
}
function ay_ops_clear_dir(string $dir): int {
    $n=0;if(!is_dir($dir))return 0;
    foreach(new DirectoryIterator($dir) as $f){if($f->isDot()||!$f->isFile())continue;$p=$f->getPathname();if(@unlink($p))$n++;}return $n;
}

if ($_SERVER['REQUEST_METHOD']==='POST') {
    if(!hash_equals($csrf,(string)($_POST['_csrf']??''))){http_response_code(403);exit('درخواست معتبر نیست. صفحه را تازه‌سازی کن.');}
    $action=(string)($_POST['_action']??'');
    try {
        if($action==='telegram_getme'){
            $r=ay_ops_tg_call((string)($GLOBALS['APIKEY']??''),'getMe');
            if(!empty($r['ok'])){$u=(string)($r['result']['username']??'');$flash['ok']='Telegram API پاسخ داد'.($u!==''?'؛ @'.$u.' آنلاین است.':'.');ay_ops_log($pdo,$action,'ok',['username'=>$u]);}
            else{throw new RuntimeException((string)($r['description']??'Telegram API پاسخ معتبر نداد.'));}
        } elseif($action==='webhook_info') {
            $r=ay_ops_tg_call((string)($GLOBALS['APIKEY']??''),'getWebhookInfo');
            if(empty($r['ok']))throw new RuntimeException((string)($r['description']??'دریافت Webhook ناموفق بود.'));
            $_SESSION['ay_webhook_info']=$r['result']??[];$url=(string)(($r['result']['url']??''));
            $flash['ok']=$url!==''?'Webhook فعلی دریافت شد.':'Telegram می‌گوید Webhook فعالی ثبت نشده است.';ay_ops_log($pdo,$action,'ok',['url_host'=>parse_url($url,PHP_URL_HOST),'pending'=>(int)($r['result']['pending_update_count']??0)]);
        } elseif($action==='set_webhook') {
            $url=ay_ops_expected_webhook();if($url==='')throw new RuntimeException('دامنه ربات در config.php تنظیم نشده است.');
            $params=['url'=>$url,'drop_pending_updates'=>'false'];$secret=ay_ops_setting($pdo,'webhook_secret_token','');if($secret!=='')$params['secret_token']=$secret;
            $r=ay_ops_tg_call((string)($GLOBALS['APIKEY']??''),'setWebhook',$params);if(empty($r['ok']))throw new RuntimeException((string)($r['description']??'ثبت Webhook ناموفق بود.'));
            $flash['ok']='Webhook روی آدرس اصلی ربات ثبت شد.';ay_ops_log($pdo,$action,'ok',['url_host'=>parse_url($url,PHP_URL_HOST),'has_secret'=>$secret!==''?1:0]);
        } elseif($action==='clear_cache') {
            $count=ay_ops_clear_dir(__DIR__.'/../storage/cache');$flash['ok']=$count.' فایل Cache پاک شد؛ داده کاربر یا تنظیمات حذف نشد.';ay_ops_log($pdo,$action,'ok',['files'=>$count]);
        } elseif($action==='support_bundle') {
            $tables=['user','invoice','Payment_report','marzban_panel','product','textbot','premium_emojis'];$counts=[];foreach($tables as $t)$counts[$t]=ay_ops_count($pdo,$t);
            $checks=[
              'php_version'=>PHP_VERSION,'sapi'=>PHP_SAPI,'os'=>PHP_OS_FAMILY,
              'extensions'=>['curl'=>extension_loaded('curl'),'openssl'=>extension_loaded('openssl'),'pdo_mysql'=>extension_loaded('pdo_mysql'),'json'=>extension_loaded('json'),'mbstring'=>extension_loaded('mbstring')],
              'writable'=>['storage'=>is_writable(__DIR__.'/../storage'),'cache'=>is_writable(__DIR__.'/../storage/cache'),'logs'=>is_writable(__DIR__.'/../logs')],
              'installer_present'=>is_dir(__DIR__.'/../installer'),'bot_token_configured'=>trim((string)($GLOBALS['APIKEY']??''))!=='','domain_configured'=>trim((string)($GLOBALS['domainhosts']??''))!=='',
              'expected_webhook'=>ay_ops_expected_webhook(),'table_counts'=>$counts,'version'=>trim((string)@file_get_contents(__DIR__.'/../version')),
            ];
            ay_ops_log($pdo,$action,'ok');ay_ops_download('itzaydin-support-'.date('Ymd-His').'.json',['product'=>'iTzAYDiN-BOT','generated_at'=>date(DATE_ATOM),'diagnostics'=>$checks]);
        } elseif($action==='core_backup') {
            if(empty($_POST['confirm_private']))throw new RuntimeException('برای Backup خصوصی، تیک تأیید را بزن. این فایل می‌تواند اطلاعات حساس داشته باشد.');
            $allow=['setting','textbot','PaySetting','shopSetting','marzban_panel','product','premium_emojis','discount','codeDiscount','admin'];
            $data=[];$meta=[];
            foreach($allow as $t){if(!ay_ops_table_exists($pdo,$t))continue;try{$rows=$pdo->query("SELECT * FROM `{$t}` LIMIT 10000")->fetchAll(PDO::FETCH_ASSOC);$data[$t]=$rows;$meta[$t]=count($rows);}catch(Throwable $e){$data[$t]=['_error'=>$e->getMessage()];}}
            ay_ops_log($pdo,$action,'ok',['tables'=>$meta]);ay_ops_download('itzaydin-core-private-'.date('Ymd-His').'.json',['warning'=>'PRIVATE BACKUP — contains configuration and may contain credentials. Keep it private.','product'=>'iTzAYDiN-BOT','version'=>trim((string)@file_get_contents(__DIR__.'/../version')),'generated_at'=>date(DATE_ATOM),'tables'=>$data]);
        }
    } catch(Throwable $e){$flash['err']=$e->getMessage();ay_ops_log($pdo,$action?:'unknown','error',['message'=>$e->getMessage()]);}
}

$health=[];
$health[]=['name'=>'PHP','ok'=>version_compare(PHP_VERSION,'8.1.0','>='),'value'=>PHP_VERSION,'hint'=>version_compare(PHP_VERSION,'8.5.0','>=')?'PHP 8.5+ روی بعضی هاست‌ها Handler ناسازگار دارد؛ اگر 403 PHP دیدی 8.3/8.4 را تست کن.':'نسخه مناسب برای اجرای ربات.'];
foreach(['curl'=>'cURL','openssl'=>'OpenSSL','pdo_mysql'=>'PDO MySQL','json'=>'JSON','mbstring'=>'Mbstring'] as $ext=>$label)$health[]=['name'=>$label,'ok'=>extension_loaded($ext),'value'=>extension_loaded($ext)?'فعال':'خاموش','hint'=>''];
try{$pdo->query('SELECT 1');$dbOk=true;}catch(Throwable $e){$dbOk=false;}$health[]=['name'=>'Database','ok'=>$dbOk,'value'=>$dbOk?'Online':'Offline','hint'=>''];
foreach(['storage'=>__DIR__.'/../storage','cache'=>__DIR__.'/../storage/cache','logs'=>__DIR__.'/../logs'] as $label=>$path)$health[]=['name'=>'Write '.$label,'ok'=>is_dir($path)&&is_writable($path),'value'=>(is_dir($path)&&is_writable($path))?'Writable':'Check permission','hint'=>$path];
$free=@disk_free_space(__DIR__);$total=@disk_total_space(__DIR__);$diskPct=($free!==false&&$total>0)?round(($free/$total)*100,1):null;$health[]=['name'=>'Disk Free','ok'=>$diskPct===null||$diskPct>8,'value'=>$diskPct===null?'—':$diskPct.'%','hint'=>''];
$healthOk=count(array_filter($health,fn($x)=>!empty($x['ok'])));$healthTotal=count($health);
$expectedWebhook=ay_ops_expected_webhook();$wh=$_SESSION['ay_webhook_info']??null;unset($_SESSION['ay_webhook_info']);
$tableNames=['user'=>'مرکز کاربران','invoice'=>'سفارش‌ها','Payment_report'=>'پرداخت‌ها','marzban_panel'=>'پنل‌ها','product'=>'پلن‌ها','textbot'=>'متن‌ها','premium_emojis'=>'Premium Emoji'];$tableStats=[];foreach($tableNames as $t=>$label)$tableStats[]=['table'=>$t,'label'=>$label,'count'=>ay_ops_count($pdo,$t)];
$security=[];
$security[]=['ok'=>!is_dir(__DIR__.'/../installer'),'title'=>'Installer','text'=>is_dir(__DIR__.'/../installer')?'پوشه installer هنوز روی سرور وجود دارد؛ بعد از اتمام نصب حذف یا محدودش کن.':'Installer در مسیر پروژه دیده نشد.'];
$configPerm=@fileperms(__DIR__.'/../config.php');$configMode=$configPerm===false?'—':substr(sprintf('%o',$configPerm),-4);$security[]=['ok'=>in_array($configMode,['0600','0640','0644'],true),'title'=>'config.php','text'=>'Permission فعلی: '.$configMode];
$security[]=['ok'=>trim((string)($GLOBALS['APIKEY']??''))!=='','title'=>'Bot Token','text'=>trim((string)($GLOBALS['APIKEY']??''))!==''?'تنظیم شده و در UI نمایش داده نمی‌شود.':'Bot Token خالی است.'];
$security[]=['ok'=>ay_ops_setting($pdo,'webhook_secret_token','')!=='','title'=>'Webhook Secret','text'=>ay_ops_setting($pdo,'webhook_secret_token','')!==''?'Secret Token برای Webhook ذخیره شده.':'Webhook Secret خالی است؛ نصب/مهاجرت را بررسی کن.'];
$history=[];try{$history=$pdo->query('SELECT * FROM itz_ops_history ORDER BY id DESC LIMIT 20')->fetchAll(PDO::FETCH_ASSOC)?:[];}catch(Throwable $e){}
?>
<!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 Operations | 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>
.ops-hero{padding:22px;border:1px solid var(--border-soft);border-radius:24px;background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 13%,var(--surface-2)),var(--surface-2));display:flex;justify-content:space-between;gap:20px;align-items:center}.ops-kicker{font:800 11px monospace;letter-spacing:2px;color:var(--accent)}.ops-score{width:84px;height:84px;border-radius:24px;display:grid;place-items:center;background:var(--surface-3);border:1px solid var(--border-mid);font-size:22px;font-weight:900}.ops-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:14px;margin-top:14px}.ops-card{padding:16px;border:1px solid var(--border-soft);border-radius:19px;background:var(--surface-2)}.ops-card h3{margin:0 0 10px}.ops-check{display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:start;padding:9px 0;border-bottom:1px solid var(--border-soft)}.ops-check:last-child{border-bottom:0}.ops-dot{width:10px;height:10px;border-radius:50%;margin-top:6px;background:#ef4444;box-shadow:0 0 0 5px rgba(239,68,68,.08)}.ops-dot.ok{background:#22c55e;box-shadow:0 0 0 5px rgba(34,197,94,.08)}.ops-check small{display:block;color:var(--text-muted);word-break:break-word}.ops-value{font:700 11px monospace;color:var(--text-muted);direction:ltr}.ops-actions{display:flex;gap:8px;flex-wrap:wrap}.ops-stat{display:flex;align-items:center;justify-content:space-between;padding:10px 0;border-bottom:1px solid var(--border-soft)}.ops-stat:last-child{border:0}.ops-stat b{font-size:18px}.ops-private{padding:12px;border-radius:14px;background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.22);font-size:12px;line-height:1.9}.ops-history{max-height:340px;overflow:auto}.ops-log{display:grid;grid-template-columns:auto 1fr auto;gap:10px;padding:9px 0;border-bottom:1px solid var(--border-soft);font-size:12px}.ops-log code{direction:ltr}.ops-webhook{font-size:12px;direction:ltr;text-align:left;word-break:break-all;padding:10px;border-radius:12px;background:var(--surface-3)}@media(max-width:640px){.ops-hero{align-items:flex-start;flex-direction:column}.ops-score{width:100%;height:54px}.ops-grid{grid-template-columns:1fr}}
</style></head><body><section id="container"><?php include 'header.php';?><section id="main-content"><div class="wrapper">
<div class="ops-hero"><div><div class="ops-kicker">iTz • OPERATIONS & RELIABILITY</div><h1 style="margin:6px 0">iTz Operations</h1><p style="margin:0;color:var(--text-muted)">سلامت ربات، Webhook، Backup خصوصی، Cache و چک امنیتی را از یک نقطه کنترل کن؛ بدون نمایش Secretها.</p></div><div class="ops-score"><?php echo $healthOk;?>/<?php echo $healthTotal;?></div></div>
<?php if($flash['ok']):?><div class="alert alert-success" style="margin-top:14px"><?php echo htmlspecialchars($flash['ok'],ENT_QUOTES,'UTF-8');?></div><?php endif;?><?php if($flash['err']):?><div class="alert alert-danger" style="margin-top:14px"><?php echo htmlspecialchars($flash['err'],ENT_QUOTES,'UTF-8');?></div><?php endif;?>
<div class="ops-grid">
<div class="ops-card"><h3>🫀 Health Matrix</h3><?php foreach($health as $h):?><div class="ops-check"><span class="ops-dot <?php echo $h['ok']?'ok':'';?>"></span><div><b><?php echo htmlspecialchars($h['name'],ENT_QUOTES);?></b><?php if($h['hint']!==''):?><small><?php echo htmlspecialchars($h['hint'],ENT_QUOTES,'UTF-8');?></small><?php endif;?></div><span class="ops-value"><?php echo htmlspecialchars((string)$h['value'],ENT_QUOTES);?></span></div><?php endforeach;?></div>
<div class="ops-card"><h3>🤖 Telegram & Webhook</h3><div class="ops-webhook"><?php echo htmlspecialchars($expectedWebhook?:'Domain not configured',ENT_QUOTES);?></div><div class="ops-actions" style="margin-top:12px"><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><button class="btn btn-outline btn-sm" name="_action" value="telegram_getme">تست Bot API</button></form><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><button class="btn btn-outline btn-sm" name="_action" value="webhook_info">وضعیت Webhook</button></form><form method="post" onsubmit="return confirm('Webhook روی آدرس اصلی ربات ثبت شود؟')"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><button class="btn btn-primary btn-sm" name="_action" value="set_webhook">Repair Webhook</button></form></div><?php if(is_array($wh)):?><div style="margin-top:12px;font-size:12px;color:var(--text-muted)"><div>URL: <code><?php echo htmlspecialchars((string)($wh['url']??'—'),ENT_QUOTES);?></code></div><div>Pending: <b><?php echo (int)($wh['pending_update_count']??0);?></b> · Last error: <?php echo htmlspecialchars((string)($wh['last_error_message']??'ندارد'),ENT_QUOTES,'UTF-8');?></div></div><?php endif;?></div>
<div class="ops-card"><h3>📦 Core Data Snapshot</h3><?php foreach($tableStats as $s):?><div class="ops-stat"><span><?php echo htmlspecialchars($s['label'],ENT_QUOTES,'UTF-8');?></span><b><?php echo $s['count']===null?'—':number_format($s['count']);?></b></div><?php endforeach;?></div>
<div class="ops-card"><h3>🛡 Security Check</h3><?php foreach($security as $s):?><div class="ops-check"><span class="ops-dot <?php echo $s['ok']?'ok':'';?>"></span><div><b><?php echo htmlspecialchars($s['title'],ENT_QUOTES,'UTF-8');?></b><small><?php echo htmlspecialchars($s['text'],ENT_QUOTES,'UTF-8');?></small></div></div><?php endforeach;?></div>
<div class="ops-card"><h3>🧰 Safe Tools</h3><div class="ops-actions"><form method="post"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><button class="btn btn-outline btn-sm" name="_action" value="support_bundle">Support Bundle</button></form><form method="post" onsubmit="return confirm('Cache موقت برنامه پاک شود؟')"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><button class="btn btn-outline btn-sm" name="_action" value="clear_cache">پاکسازی Cache</button></form></div><p style="font-size:12px;color:var(--text-muted);line-height:1.9">Support Bundle هیچ Token یا API Key خامی داخل فایل نمی‌گذارد و برای عیب‌یابی مناسب است.</p><div class="ops-private"><b>Backup خصوصی</b><br>این خروجی می‌تواند Token، API Key و اطلاعات تنظیمات را داشته باشد؛ فقط برای Backup شخصی و جای امن استفاده کن.<form method="post" style="margin-top:8px" onsubmit="return confirm('Backup خصوصی دانلود شود؟ فایل را عمومی نکن.')"><input type="hidden" name="_csrf" value="<?php echo htmlspecialchars($csrf,ENT_QUOTES);?>"><label style="display:flex;gap:8px;align-items:center;margin-bottom:8px"><input type="checkbox" name="confirm_private" value="1" required> خطر حساس بودن فایل را می‌دانم</label><button class="btn btn-soft-purple btn-sm" name="_action" value="core_backup">دانلود Core Backup</button></form></div></div>
<div class="ops-card"><h3>🧾 Operations Timeline</h3><div class="ops-history"><?php if(!$history):?><div style="color:var(--text-muted);font-size:12px">هنوز عملیاتی ثبت نشده.</div><?php endif;?><?php foreach($history as $r):?><div class="ops-log"><span class="badge <?php echo ($r['status_name']??'')==='ok'?'badge-active':'badge-danger';?>"><?php echo htmlspecialchars($r['status_name']??'',ENT_QUOTES);?></span><div><b><?php echo htmlspecialchars($r['action_name']??'',ENT_QUOTES);?></b><small style="display:block;color:var(--text-muted)"><?php echo htmlspecialchars($r['admin_user']??'',ENT_QUOTES,'UTF-8');?></small></div><code><?php echo !empty($r['created_at'])?htmlspecialchars(date('m-d H:i',(int)$r['created_at']),ENT_QUOTES):'—';?></code></div><?php endforeach;?></div></div>
</div></div></section></section></body></html>
