<?php
declare(strict_types=1);

function mobE(mixed $v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
function mobNorm(string $v): string {
    $v=trim($v); $v=function_exists('mb_strtolower')?mb_strtolower($v,'UTF-8'):strtolower($v);
    $v=strtr($v,['á'=>'a','à'=>'a','â'=>'a','ã'=>'a','ä'=>'a','é'=>'e','è'=>'e','ê'=>'e','ë'=>'e','í'=>'i','ì'=>'i','î'=>'i','ï'=>'i','ó'=>'o','ò'=>'o','ô'=>'o','õ'=>'o','ö'=>'o','ú'=>'u','ù'=>'u','û'=>'u','ü'=>'u','ç'=>'c']);
    return preg_replace('/[^a-z0-9]+/','',$v)??'';
}
function mobText(mixed $v,int $max=255): string { $v=trim((string)$v); return function_exists('mb_substr')?mb_substr($v,0,$max,'UTF-8'):substr($v,0,$max); }
function mobNullable(mixed $v,int $max=255): ?string { $v=mobText($v,$max); return $v===''?null:$v; }
function mobTableExists(mysqli $db,string $table): bool { $x=$db->real_escape_string($table); $r=$db->query("SHOW TABLES LIKE '{$x}'"); return $r instanceof mysqli_result && $r->num_rows>0; }
function mobCsrf(): string { if(empty($_SESSION['mob_csrf'])) $_SESSION['mob_csrf']=bin2hex(random_bytes(24)); return (string)$_SESSION['mob_csrf']; }
function mobCheckCsrf(): void { $a=(string)($_POST['csrf_token']??'');$b=(string)($_SESSION['mob_csrf']??'');if($a===''||$b===''||!hash_equals($b,$a))throw new RuntimeException('Sessão expirada. Atualize a página.'); }
function mobFlash(string $tipo,string $msg): void { $_SESSION['mob_flash']=['tipo'=>$tipo,'msg'=>$msg]; }
function mobGetFlash(): ?array { $f=$_SESSION['mob_flash']??null;unset($_SESSION['mob_flash']);return is_array($f)?$f:null; }
function mobRedirect(string $url): never { header('Location: '.$url);exit; }
function mobUsuario(): string { return trim((string)($_SESSION['usuario']??'Usuário')); }
function mobEhRenan(): bool { return mobNorm(mobUsuario())==='renan'; }
function mobConfig(mysqli $db): array {
    $r=$db->query('SELECT * FROM ti_mobile_config WHERE id=1 LIMIT 1');
    return $r?($r->fetch_assoc()?:[]):[];
}
function mobData(?string $d): string { if(!$d)return 'Nunca';$t=strtotime($d);return $t?date('d/m/Y H:i',$t):$d; }
function mobAgo(?string $d): string {
    if(!$d)return 'nunca comunicou';$t=strtotime($d);if(!$t)return $d;$s=max(0,time()-$t);
    if($s<60)return 'agora';if($s<3600)return floor($s/60).' min';if($s<86400)return floor($s/3600).' h';return floor($s/86400).' dias';
}
function mobEstadoComunicacao(?string $d,int $offlineHours=168,int $recentHours=2,int $silentHours=24): array {
    if(!$d)return ['codigo'=>'NUNCA','label'=>'Nunca comunicou','class'=>'danger'];$t=strtotime($d)?:0;$age=time()-$t;
    if($age<=$recentHours*3600)return ['codigo'=>'RECENTE','label'=>'Comunicando recentemente','class'=>'ok'];
    if($age<=$silentHours*3600)return ['codigo'=>'AGUARDANDO','label'=>'Aguardando próxima comunicação','class'=>'warn'];
    if($age<=$offlineHours*3600)return ['codigo'=>'SEM_COMUNICACAO','label'=>'Sem comunicação','class'=>'warn'];
    return ['codigo'=>'OFFLINE','label'=>'Offline prolongado','class'=>'danger'];
}
function mobScore(array $d,array $cfg): int {
    $score=100;$total=max(1,(int)($d['armazenamento_total_mb']??0));$free=(int)($d['armazenamento_livre_mb']??0);$pct=$free/$total*100;
    if($pct<=(int)($cfg['storage_critical_percent']??10))$score-=25;elseif($pct<20)$score-=10;
    $sdk=(int)($d['sdk_int']??0);if($sdk>0&&$sdk<29)$score-=20;elseif($sdk>0&&$sdk<31)$score-=10;
    $patch=(string)($d['security_patch']??'');if($patch&&($pt=strtotime($patch))&&time()-$pt>365*86400)$score-=15;
    $ram=(int)($d['ram_total_mb']??0);if($ram>0&&$ram<3072)$score-=15;elseif($ram>0&&$ram<4096)$score-=5;
    if(($d['status']??'')!=='ATIVO')$score-=30;
    return max(0,min(100,$score));
}
function mobLinkSmartphone(mysqli $db,?string $patrimonio,?string $imei): ?int {
    if(!mobTableExists($db,'telecom_smartphones'))return null;
    if($patrimonio){$stmt=$db->prepare('SELECT id FROM telecom_smartphones WHERE patrimonio=? LIMIT 1');$stmt->bind_param('s',$patrimonio);$stmt->execute();$x=$stmt->get_result()->fetch_assoc();$stmt->close();if($x)return (int)$x['id'];}
    if($imei){$stmt=$db->prepare('SELECT id FROM telecom_smartphones WHERE imei1=? OR imei2=? LIMIT 1');$stmt->bind_param('ss',$imei,$imei);$stmt->execute();$x=$stmt->get_result()->fetch_assoc();$stmt->close();if($x)return (int)$x['id'];}
    return null;
}
function mobLinkAtivo(mysqli $db,?string $patrimonio,?string $serie,?string $imei): ?int {
    if(!mobTableExists($db,'ti_ativos'))return null;$compact=static fn(?string $v):string=>preg_replace('/[^a-z0-9]+/i','',strtolower((string)$v))??'';$pat=$compact($patrimonio);$ser=$compact($serie);$sec=$compact($imei);if($pat===''&&$ser===''&&$sec==='')return null;
    $stmt=$db->prepare("SELECT id FROM ti_ativos WHERE (?<>'' AND patrimonio_normalizado=?) OR (?<>'' AND serie_normalizada=?) OR (?<>'' AND identificador_secundario=?) LIMIT 1");$stmt->bind_param('ssssss',$pat,$pat,$ser,$ser,$sec,$sec);$stmt->execute();$row=$stmt->get_result()->fetch_assoc();$stmt->close();return $row?(int)$row['id']:null;
}
function mobAudit(mysqli $db,string $acao,?int $deviceId=null,?string $detail=null): void {
    if(!mobTableExists($db,'ti_mobile_auditoria'))return;$actor=mobUsuario();$ip=substr((string)($_SERVER['REMOTE_ADDR']??''),0,45);$stmt=$db->prepare('INSERT INTO ti_mobile_auditoria(dispositivo_id,acao,ator,ip_remoto,detalhes) VALUES(?,?,?,?,?)');$stmt->bind_param('issss',$deviceId,$acao,$actor,$ip,$detail);$stmt->execute();$stmt->close();
}
function mobAgentSourceExists(): bool { return is_file(__DIR__.'/downloads/Agente-TI-Extrema-FONTE.zip'); }
function mobApkExists(): bool { return is_file(__DIR__.'/downloads/Agente-TI-Extrema.apk'); }
function mobApkPublishedAt(): ?string { $file=__DIR__.'/downloads/Agente-TI-Extrema.apk';return is_file($file)?date('d/m/Y H:i',(int)filemtime($file)):null; }
function mobDebugApkExists(): bool { return is_file(__DIR__.'/downloads/Agente-TI-Extrema-debug.apk'); }
?>
