<?php
/** Execução técnica de exclusão/anomização solicitada pelo titular. */

function afPrivacyColumnExists(PDO $pdo,string $table,string $column): bool
{
    static $cache=[];$key=$table.'.'.$column;if(isset($cache[$key]))return $cache[$key];
    try{$st=$pdo->prepare('SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? AND COLUMN_NAME=? LIMIT 1');$st->execute([$table,$column]);return $cache[$key]=(bool)$st->fetchColumn();}catch(Throwable $e){return $cache[$key]=false;}
}
function afPrivacyDeleteBy(PDO $pdo,string $table,string $column,int $id): int
{
    if(!afPrivacyTableExists($pdo,$table)||!afPrivacyColumnExists($pdo,$table,$column))return 0;
    $st=$pdo->prepare("DELETE FROM `{$table}` WHERE `{$column}`=?");$st->execute([$id]);return $st->rowCount();
}
function afPrivacyDeleteByIds(PDO $pdo,string $table,string $column,array $ids): int
{
    $ids=array_values(array_unique(array_filter(array_map('intval',$ids),fn($v)=>$v>0)));
    if(!$ids||!afPrivacyTableExists($pdo,$table)||!afPrivacyColumnExists($pdo,$table,$column))return 0;
    $marks=implode(',',array_fill(0,count($ids),'?'));$st=$pdo->prepare("DELETE FROM `{$table}` WHERE `{$column}` IN ({$marks})");$st->execute($ids);return $st->rowCount();
}
function afPrivacyExecutionLog(PDO $pdo,int $requestId,int $subjectId,int $adminId,string $scope,string $status,array $details=[]): void
{
    if(!afPrivacyTableExists($pdo,'af_privacy_execution_logs'))return;
    $pdo->prepare('INSERT INTO af_privacy_execution_logs(privacy_request_id,subject_user_id,admin_user_id,scope_key,status,details_json,ip_address,created_at) VALUES (?,?,?,?,?,?,?,NOW())')
        ->execute([$requestId,$subjectId,$adminId,$scope,$status,$details?json_encode($details,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES):null,clientIp()]);
}
function afPrivacyExecuteHistoryDeletion(PDO $pdo,int $subjectId): array
{
    $counts=[];
    // Inscrições e resultados de eventos infantis pertencentes ao titular são removidos em cascata.
    $counts['af_controlled_event_participants']=afPrivacyDeleteBy($pdo,'af_controlled_event_participants','minor_user_id',$subjectId);
    $counts['af_controlled_event_consents_guardian']=afPrivacyDeleteBy($pdo,'af_controlled_event_consents','guardian_user_id',$subjectId);
    $st=$pdo->prepare('SELECT id FROM af_partidas WHERE usuario_id=?');$st->execute([$subjectId]);$matchIds=array_map('intval',$st->fetchAll(PDO::FETCH_COLUMN)?:[]);
    foreach(['af_safe_camera_events','af_safe_camera_sessions','af_third_party_detections','af_live_comments','af_live_spectator_restrictions','af_partida_eventos','af_partida_espectadores','af_partida_interacoes','af_partida_combo_sequencias'] as $table){
        $column=$table==='af_third_party_detections'?'partida_id':'partida_id';
        $counts[$table]=afPrivacyDeleteByIds($pdo,$table,$column,$matchIds);
    }
    foreach([
        ['af_batalha_eventos','usuario_id'],['af_batalha_jogadores','usuario_id'],['af_competicao_participantes','usuario_id'],
        ['af_compartilhamentos','usuario_id'],['af_convites_virais','usuario_id'],['af_progressao_usuario','usuario_id'],
        ['af_ranking','usuario_id'],['af_usuario_conquistas','usuario_id'],['af_usuario_equipamentos','usuario_id'],
        ['af_usuario_missoes','usuario_id'],['af_usuario_recompensas','usuario_id'],['af_xp_eventos','usuario_id'],
        ['af_partida_combo_sequencias','usuario_id'],['af_partida_espectadores','usuario_id'],['af_partida_interacoes','usuario_id'],
        ['af_partida_eventos','usuario_id'],['af_safe_camera_events','usuario_id'],['af_safe_camera_sessions','usuario_id'],
        ['af_third_party_detections','minor_usuario_id'],['af_notificacoes','usuario_id']
    ] as [$table,$column])$counts[$table]=($counts[$table]??0)+afPrivacyDeleteBy($pdo,$table,$column,$subjectId);
    $counts['af_partidas']=afPrivacyDeleteBy($pdo,'af_partidas','usuario_id',$subjectId);
    if(afPrivacyTableExists($pdo,'af_seguidores')){
        $st=$pdo->prepare('DELETE FROM af_seguidores WHERE seguidor_id=? OR seguido_id=?');$st->execute([$subjectId,$subjectId]);$counts['af_seguidores']=$st->rowCount();
    }
    $pdo->prepare("UPDATE af_usuarios SET nivel=1,xp_total=0,aura_total=0,melhor_pontuacao=0,total_partidas=0,total_vitorias=0,total_likes=0,total_superlikes=0,titulo='Aura Initiate',atualizado_em=NOW() WHERE id=?")->execute([$subjectId]);
    return ['matches'=>count($matchIds),'deleted_rows'=>array_sum($counts),'tables'=>$counts];
}
function afPrivacyExecuteAccountDeletion(PDO $pdo,int $subjectId): array
{
    $history=afPrivacyExecuteHistoryDeletion($pdo,$subjectId);
    $st=$pdo->prepare('SELECT foto_perfil FROM af_usuarios WHERE id=? LIMIT 1');$st->execute([$subjectId]);$photo=(string)($st->fetchColumn()?:'');
    foreach([
        ['af_approved_contacts','minor_usuario_id'],['af_approved_contacts','guardian_usuario_id'],
        ['af_feature_permissions','minor_usuario_id'],['af_feature_permissions','guardian_usuario_id'],
        ['af_guardian_alerts','minor_usuario_id'],['af_guardian_alerts','guardian_usuario_id'],
        ['af_guardian_controls','minor_usuario_id'],['af_guardian_controls','guardian_usuario_id'],
        ['af_guardian_control_audit','minor_usuario_id'],['af_guardian_control_audit','guardian_usuario_id'],
        ['af_guardian_family_challenges','minor_usuario_id'],['af_guardian_family_challenges','guardian_usuario_id'],
        ['af_parental_consents','minor_usuario_id'],['af_parental_consents','guardian_usuario_id'],
        ['af_guardian_invitations','minor_usuario_id'],['af_minor_access_logs','minor_usuario_id'],
        ['af_minor_policy_snapshots','minor_usuario_id'],['af_minor_policy_decision_logs','usuario_id'],
        ['af_minor_safety_settings','minor_usuario_id'],['af_camera_privacy_settings','minor_usuario_id'],
        ['af_user_blocks','blocker_user_id'],['af_user_blocks','blocked_user_id']
    ] as [$table,$column])afPrivacyDeleteBy($pdo,$table,$column,$subjectId);
    if(afPrivacyTableExists($pdo,'af_controlled_event_participants')&&afPrivacyTableExists($pdo,'af_guardian_minor_links')){
        $st=$pdo->prepare('DELETE FROM af_controlled_event_participants WHERE guardian_link_id IN (SELECT id FROM af_guardian_minor_links WHERE guardian_usuario_id=?)');$st->execute([$subjectId]);
    }
    if(afPrivacyTableExists($pdo,'af_guardian_minor_links')){
        $st=$pdo->prepare('DELETE FROM af_guardian_minor_links WHERE guardian_usuario_id=? OR minor_usuario_id=?');$st->execute([$subjectId,$subjectId]);
    }
    foreach([['af_guardian_accounts','usuario_id'],['af_oauth_contas','usuario_id'],['af_password_resets','usuario_id'],['af_sessoes','usuario_id'],['af_dispositivos','usuario_id'],['af_dispositivo_contas','usuario_id'],['af_age_assurance_codes','usuario_id'],['af_age_verifications','usuario_id'],['af_user_age_profiles','usuario_id'],['af_perfis','usuario_id']] as [$t,$c])afPrivacyDeleteBy($pdo,$t,$c,$subjectId);
    if(afPrivacyTableExists($pdo,'af_controlled_event_organizers')){
        $pdo->prepare("UPDATE af_controlled_event_organizers SET organization_name='Conta excluída',contact_phone=NULL,status='revoked',suspension_reason='Conta do titular excluída',updated_at=NOW() WHERE usuario_id=?")->execute([$subjectId]);
    }
    $suffix=bin2hex(random_bytes(6));$username='excluido_'.$subjectId.'_'.$suffix;$email='excluido+'.$subjectId.'+'.$suffix.'@invalid.local';$aura='DEL-'.str_pad((string)($subjectId%100000),5,'0',STR_PAD_LEFT).'-'.strtoupper(substr($suffix,0,3));
    $password=password_hash(bin2hex(random_bytes(32)),PASSWORD_DEFAULT);
    $pdo->prepare("UPDATE af_usuarios SET nome='Usuário excluído',username=?,email=?,senha=?,foto_perfil=NULL,foto_externa=NULL,aura_id=?,auth_provider='local',email_verificado_em=NULL,status=0,seguranca_status='restrito',risco_conta=0,suspenso_ate=NULL,token_recuperacao=NULL,token_expira=NULL,atualizado_em=NOW() WHERE id=?")
        ->execute([$username,$email,$password,substr($aura,0,15),$subjectId]);
    if($photo!=='' && !str_contains($photo,'://')){
        $candidate=ROOT_PATH.'/'.ltrim($photo,'/');$allowed=realpath(ROOT_PATH.'/assets/uploads/avatars');$real=is_file($candidate)?realpath($candidate):false;
        if($allowed&&$real&&str_starts_with($real,$allowed.DIRECTORY_SEPARATOR))@unlink($real);
    }
    return ['history'=>$history,'account_anonymized'=>true,'sessions_revoked'=>true];
}
function afPrivacyExecuteDeletionRequest(PDO $pdo,int $privacyRequestId,int $adminId,string $response=''): array
{
    $st=$pdo->prepare("SELECT r.*,d.id deletion_id,d.scope_key,d.status deletion_status FROM af_privacy_requests r JOIN af_deletion_requests d ON d.privacy_request_id=r.id WHERE r.id=? LIMIT 1 FOR UPDATE");
    $st->execute([$privacyRequestId]);$row=$st->fetch();if(!$row)throw new RuntimeException('Registro de exclusão não encontrado.');
    if((string)$row['deletion_status']==='completed')return ['already_completed'=>true];
    $subjectId=(int)$row['subject_user_id'];$scope=(string)$row['scope_key'];
    afPrivacyExecutionLog($pdo,$privacyRequestId,$subjectId,$adminId,$scope,'started');
    $result=$scope==='account'?afPrivacyExecuteAccountDeletion($pdo,$subjectId):afPrivacyExecuteHistoryDeletion($pdo,$subjectId);
    $pdo->prepare("UPDATE af_deletion_requests SET status='completed',completed_at=NOW(),retention_reason=NULL,updated_at=NOW() WHERE id=?")->execute([(int)$row['deletion_id']]);
    $pdo->prepare("UPDATE af_privacy_requests SET status='completed',response_text=?,assigned_admin_id=?,completed_at=NOW(),updated_at=NOW() WHERE id=?")
        ->execute([$response?:'Solicitação executada tecnicamente e registrada em auditoria.',$adminId,$privacyRequestId]);
    afPrivacyExecutionLog($pdo,$privacyRequestId,$subjectId,$adminId,$scope,'completed',$result);
    if(function_exists('afStage24TableExists') && afStage24TableExists($pdo,'af_data_deletion_logs')){
        $protocolHash=function_exists('afStage24Hash')?afStage24Hash($privacyRequestId.'|'.$subjectId.'|'.$scope.'|completed'):
            hash('sha256',$privacyRequestId.'|'.$subjectId.'|'.$scope.'|completed');
        $pdo->prepare('INSERT INTO af_data_deletion_logs(privacy_request_id,subject_user_id,admin_user_id,scope_key,status,protocol_hash,details_json,ip_hash,created_at) VALUES (?,?,?,?,?,?,?,?,NOW())')
            ->execute([$privacyRequestId,$subjectId,$adminId,$scope,'completed',$protocolHash,json_encode($result,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),function_exists('afStage24IpHash')?afStage24IpHash():null]);
    }
    if(function_exists('afStage24AuditLog')){
        afStage24AuditLog($pdo,'privacy_deletion_completed','privacy_request',$privacyRequestId,[],['scope'=>$scope,'result'=>$result],['actor_type'=>'admin','actor_admin_id'=>$adminId,'subject_user_id'=>$subjectId,'severity'=>'high','source'=>'privacy_deletion']);
    }
    return $result;
}
