<?php
/**
 * AURA FARMING — Verificação interna do responsável, sem SMS e sem provedor pago.
 *
 * Camadas utilizadas:
 * 1. conta adulta com data de nascimento confirmada;
 * 2. declaração específica de responsabilidade;
 * 3. código enviado ao e-mail da própria conta;
 * 4. código familiar gerado dentro da conta do menor;
 * 5. conferência humana presencial ou ao vivo, sem gravação;
 * 6. impressão HMAC do número do documento, sem guardar o número;
 * 7. análise interna de risco e aprovação manual administrativa;
 * 8. consentimentos específicos e política central de menores continuam obrigatórios.
 *
 * Nenhuma cópia de documento, selfie, biometria, áudio ou vídeo é armazenada.
 */

function afGuardianVerificationConfig(PDO $pdo, string $key, mixed $default = null): mixed
{
    try {
        $st = $pdo->prepare('SELECT valor FROM af_configuracoes WHERE chave=? LIMIT 1');
        $st->execute([$key]);
        $value = $st->fetchColumn();
        return $value === false ? $default : $value;
    } catch (Throwable $e) {
        return $default;
    }
}

function afGuardianTableExists(PDO $pdo, string $table): bool
{
    static $cache = [];
    if (array_key_exists($table, $cache)) return $cache[$table];
    try {
        $st = $pdo->prepare('SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name=? LIMIT 1');
        $st->execute([$table]);
        return $cache[$table] = (bool)$st->fetchColumn();
    } catch (Throwable $e) {
        return $cache[$table] = false;
    }
}

function afGuardianColumnExists(PDO $pdo, string $table, string $column): bool
{
    static $cache = [];
    $key = $table.'.'.$column;
    if (array_key_exists($key, $cache)) 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;
    }
}

/** Mantida por compatibilidade. Telefone não é fator de verificação. */
function afGuardianPhoneVerificationRequired(PDO $pdo): bool
{
    return false;
}

/** Mantida por compatibilidade. O sistema não usa webhook de SMS. */
function afGuardianSmsAvailable(): bool
{
    return false;
}

function afGuardianMaskEmail(string $email): string
{
    $email = trim($email);
    if (!str_contains($email, '@')) return '***';
    [$local, $domain] = explode('@', $email, 2);
    $visible = mb_substr($local, 0, min(2, mb_strlen($local)));
    return $visible . str_repeat('*', max(2, mb_strlen($local) - mb_strlen($visible))) . '@' . $domain;
}

function afGuardianNormalizePhone(string $phone): string
{
    $digits = preg_replace('/\D+/', '', $phone) ?? '';
    if ($digits !== '' && (strlen($digits) < 8 || strlen($digits) > 15)) {
        throw new InvalidArgumentException('Informe um telefone válido com DDD ou deixe o campo vazio.');
    }
    return $digits;
}

function afGuardianMaskPhone(string $phone): string
{
    $digits = preg_replace('/\D+/', '', $phone) ?? '';
    if (strlen($digits) < 4) return '***';
    return str_repeat('*', max(4, strlen($digits) - 4)) . substr($digits, -4);
}


function afGuardianReviewMethods(): array
{
    return [
        'in_person' => 'Conferência presencial, sem retenção de cópia',
        'live_no_recording' => 'Conferência ao vivo, sem gravação',
    ];
}

function afGuardianIdentityFingerprint(string $documentNumber): string
{
    if(!defined('SECURITY_HASH_SALT') || strlen((string)SECURITY_HASH_SALT)<32 || hash_equals('troque-esta-chave-em-producao',(string)SECURITY_HASH_SALT)){
        throw new RuntimeException('Configure SECURITY_HASH_SALT com uma chave secreta forte antes de aprovar responsáveis.');
    }
    $normalized = strtoupper(preg_replace('/[^A-Z0-9]+/i', '', trim($documentNumber)) ?? '');
    if (strlen($normalized) < 5 || strlen($normalized) > 40) {
        throw new InvalidArgumentException('Informe um número de documento válido para gerar a impressão de segurança.');
    }
    return hash_hmac('sha256', $normalized, SECURITY_HASH_SALT.'|guardian-identity-fingerprint');
}

function afGuardianReviewChecklistKeys(): array
{
    return [
        'identity_observed' => 'A identidade e a maioridade foram conferidas ao vivo ou presencialmente.',
        'account_data_match' => 'Nome e data de nascimento conferem com a conta.',
        'legal_authority_observed' => 'O vínculo ou a autoridade legal foi conferido sem guardar cópia.',
        'family_code_checked' => 'O código familiar e o vínculo técnico foram conferidos.',
        'risk_flags_reviewed' => 'Os sinais de risco, IP, dispositivo e dependentes foram revisados.',
        'no_copy_retained' => 'Nenhuma foto, captura, áudio, vídeo ou número bruto de documento foi retido.',
    ];
}

function afGuardianGetCurrentVerification(PDO $pdo, int $usuarioId): ?array
{
    $st = $pdo->prepare('SELECT v.*,ga.usuario_id,ga.telefone,ga.status_verificacao,
            ga.email_verificado_em AS account_email_verificado_em,
            ga.telefone_verificado_em AS account_telefone_verificado_em,ga.verificado_em,
            u.nome,u.email,u.aura_id,u.data_cadastro,a.data_nascimento,a.idade_declarada,a.pais_residencia
        FROM af_guardian_accounts ga
        JOIN af_usuarios u ON u.id=ga.usuario_id
        LEFT JOIN af_user_age_profiles a ON a.usuario_id=u.id
        LEFT JOIN af_guardian_verifications v ON v.id=ga.verification_id
        WHERE ga.usuario_id=? LIMIT 1');
    $st->execute([$usuarioId]);
    return $st->fetch() ?: null;
}

function afGuardianEnsureVerification(PDO $pdo, int $usuarioId): array
{
    $account = afGuardianGarantirConta($pdo, $usuarioId, null, 'internal_layered_verification');
    if (!$account) throw new RuntimeException('Conta do responsável não encontrada.');

    $current = afGuardianGetCurrentVerification($pdo, $usuarioId);
    if ($current && !empty($current['id'])) return $current;

    $st = $pdo->prepare('INSERT INTO af_guardian_verifications
        (guardian_account_id,metodo,status,declaration_version,ip_address,user_agent,device_uuid,criado_em,atualizado_em)
        VALUES (?,\'internal_layered_review\',\'pending\',?,?,?,?,NOW(),NOW())');
    $st->execute([
        (int)$account['id'],
        (string)afGuardianVerificationConfig($pdo, 'guardian_declaration_version', '2.0'),
        clientIp(),
        substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 1000),
        deviceUuid(),
    ]);
    $verificationId = (int)$pdo->lastInsertId();
    $pdo->prepare('UPDATE af_guardian_accounts SET verification_id=?,metodo_verificacao=\'internal_layered_review\',atualizado_em=NOW() WHERE id=?')
        ->execute([$verificationId, (int)$account['id']]);

    afLogSeguranca($pdo, 'guardian_internal_verification_started', 10, ['verification_id'=>$verificationId], $usuarioId);
    return afGuardianGetCurrentVerification($pdo, $usuarioId) ?: [];
}

function afGuardianLatestInternalReview(PDO $pdo, int $usuarioId): ?array
{
    if (!afGuardianTableExists($pdo, 'af_guardian_manual_reviews')) return null;
    $st = $pdo->prepare('SELECT r.* FROM af_guardian_manual_reviews r
        JOIN af_guardian_accounts ga ON ga.id=r.guardian_account_id
        WHERE ga.usuario_id=? ORDER BY r.id DESC LIMIT 1');
    $st->execute([$usuarioId]);
    return $st->fetch() ?: null;
}

function afGuardianInternalReviewValid(PDO $pdo, int $usuarioId): bool
{
    $required = filter_var(
        afGuardianVerificationConfig($pdo, 'guardian_internal_manual_review_required', '1'),
        FILTER_VALIDATE_BOOL
    );
    if (!$required) return true;
    $review = afGuardianLatestInternalReview($pdo, $usuarioId);
    if (!$review || (string)$review['status'] !== 'approved') return false;

    $liveCheckRequired=filter_var(afGuardianVerificationConfig($pdo,'guardian_live_identity_check_required','1'),FILTER_VALIDATE_BOOL);
    $fingerprintRequired=filter_var(afGuardianVerificationConfig($pdo,'guardian_identity_fingerprint_required','1'),FILTER_VALIDATE_BOOL);
    $checklist=json_decode((string)($review['reviewer_checklist_json']??''),true);
    $checklistValid=is_array($checklist);
    if($checklistValid){foreach(array_keys(afGuardianReviewChecklistKeys()) as $key){if(empty($checklist[$key])){$checklistValid=false;break;}}}
    $evidenceInvalid=($liveCheckRequired&&!array_key_exists((string)($review['review_method']??''),afGuardianReviewMethods()))
        || ($fingerprintRequired&&empty($review['identity_fingerprint']))
        || !$checklistValid
        || empty($review['review_protocol']);
    if($evidenceInvalid){
        try{
            $pdo->prepare("UPDATE af_guardian_manual_reviews SET status='expired',valid_until=NOW(),updated_at=NOW() WHERE id=? AND status='approved'")->execute([(int)$review['id']]);
            $pdo->prepare("UPDATE af_guardian_accounts SET status_verificacao='pending',verificado_em=NULL,atualizado_em=NOW() WHERE usuario_id=?")->execute([$usuarioId]);
            $pdo->prepare("UPDATE af_guardian_minor_links SET status='pending_verification',verificado_em=NULL,atualizado_em=NOW() WHERE guardian_usuario_id=? AND status IN ('active','verified_pending_consent')")->execute([$usuarioId]);
        }catch(Throwable $e){if(defined('APP_DEBUG')&&APP_DEBUG)error_log('[AURA-GUARDIAN-EVIDENCE] '.$e->getMessage());}
        return false;
    }
    if (!empty($review['valid_until']) && strtotime((string)$review['valid_until']) <= time()) {
        try {
            $pdo->prepare("UPDATE af_guardian_manual_reviews SET status='expired',updated_at=NOW() WHERE id=? AND status='approved'")
                ->execute([(int)$review['id']]);
            $pdo->prepare("UPDATE af_guardian_accounts SET status_verificacao='pending',verificado_em=NULL,atualizado_em=NOW() WHERE usuario_id=?")
                ->execute([$usuarioId]);
            $pdo->prepare("UPDATE af_guardian_minor_links SET status='pending_verification',atualizado_em=NOW() WHERE guardian_usuario_id=? AND status IN ('active','verified_pending_consent')")
                ->execute([$usuarioId]);
        } catch (Throwable $e) {
            if (defined('APP_DEBUG') && APP_DEBUG) error_log('[AURA-GUARDIAN-EXPIRATION] '.$e->getMessage());
        }
        return false;
    }
    return true;
}

function afGuardianAdultVerified(PDO $pdo, int $usuarioId): bool
{
    $account = afGuardianBuscarConta($pdo, $usuarioId);
    return $account !== null
        && (string)($account['status_verificacao'] ?? '') === 'verified'
        && !empty($account['verificado_em'])
        && afGuardianInternalReviewValid($pdo, $usuarioId);
}

function afGuardianFamilyLinks(PDO $pdo, int $guardianUsuarioId): array
{
    $familyColumn = afGuardianColumnExists($pdo,'af_guardian_minor_links','family_confirmed_at');
    $selectFamily = $familyColumn ? 'l.family_confirmed_at' : 'NULL AS family_confirmed_at';
    $st = $pdo->prepare("SELECT l.*,{$selectFamily},m.nome minor_nome,m.username minor_username,m.aura_id minor_aura_id,
            a.idade_declarada,a.status_idade
        FROM af_guardian_minor_links l
        JOIN af_usuarios m ON m.id=l.minor_usuario_id
        LEFT JOIN af_user_age_profiles a ON a.usuario_id=m.id
        WHERE l.guardian_usuario_id=? AND l.status IN ('pending_verification','verified_pending_consent','active')
        ORDER BY l.criado_em DESC");
    $st->execute([$guardianUsuarioId]);
    $links = $st->fetchAll() ?: [];
    if (!$familyColumn && afGuardianTableExists($pdo,'af_guardian_family_challenges')) {
        foreach ($links as &$link) {
            $s=$pdo->prepare("SELECT verified_at FROM af_guardian_family_challenges WHERE link_id=? AND status='verified' ORDER BY id DESC LIMIT 1");
            $s->execute([(int)$link['id']]);
            $link['family_confirmed_at']=$s->fetchColumn() ?: null;
        }
        unset($link);
    }
    return $links;
}

function afGuardianFamilyLinkConfirmed(PDO $pdo, int $linkId): bool
{
    if ($linkId <= 0) return false;
    if (afGuardianColumnExists($pdo,'af_guardian_minor_links','family_confirmed_at')) {
        $st=$pdo->prepare('SELECT family_confirmed_at FROM af_guardian_minor_links WHERE id=? LIMIT 1');
        $st->execute([$linkId]);
        return (bool)$st->fetchColumn();
    }
    if (!afGuardianTableExists($pdo,'af_guardian_family_challenges')) return false;
    $st=$pdo->prepare("SELECT 1 FROM af_guardian_family_challenges WHERE link_id=? AND status='verified' LIMIT 1");
    $st->execute([$linkId]);
    return (bool)$st->fetchColumn();
}

function afGuardianGenerateFamilyCode(PDO $pdo, int $minorUsuarioId): array
{
    if (!afGuardianTableExists($pdo,'af_guardian_family_challenges')) {
        throw new RuntimeException('Importe a correção de segurança sem terceiros antes de gerar o código familiar.');
    }
    $link=afGuardianBuscarVinculoDoMenor($pdo,$minorUsuarioId);
    if(!$link) throw new RuntimeException('Nenhum responsável está vinculado a esta conta.');
    if((int)$link['minor_usuario_id']!==$minorUsuarioId) throw new RuntimeException('Vínculo inválido.');

    afRateLimitOrFail($pdo,'guardian_family_code_minor',(string)$minorUsuarioId,5,3600,3600);
    afRateLimitOrFail($pdo,'guardian_family_code_ip',clientIp(),15,3600,3600);

    $minutes=max(10,min(60,(int)afGuardianVerificationConfig($pdo,'guardian_family_code_expiration_minutes','20')));
    $code=str_pad((string)random_int(0,99999999),8,'0',STR_PAD_LEFT);
    $hash=hash_hmac('sha256',$code,SECURITY_HASH_SALT.'|guardian-family|'.(int)$link['id']);
    $expires=(new DateTimeImmutable('now',new DateTimeZone(APP_TIMEZONE)))->modify('+'.$minutes.' minutes')->format('Y-m-d H:i:s');

    $pdo->beginTransaction();
    try{
        $pdo->prepare("UPDATE af_guardian_family_challenges SET status='superseded',updated_at=NOW() WHERE link_id=? AND status='pending'")
            ->execute([(int)$link['id']]);
        $st=$pdo->prepare("INSERT INTO af_guardian_family_challenges
            (link_id,guardian_account_id,minor_usuario_id,guardian_usuario_id,code_hash,status,attempts,max_attempts,expires_at,created_ip,created_device_uuid,created_at,updated_at)
            VALUES (?,(SELECT id FROM af_guardian_accounts WHERE usuario_id=? LIMIT 1),?,?,?,'pending',0,5,?,?,?,NOW(),NOW())");
        $st->execute([(int)$link['id'],(int)$link['guardian_usuario_id'],$minorUsuarioId,(int)$link['guardian_usuario_id'],$hash,$expires,clientIp(),deviceUuid()]);
        $challengeId=(int)$pdo->lastInsertId();
        $pdo->commit();
    }catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}

    afLogSeguranca($pdo,'guardian_family_code_generated',10,['link_id'=>(int)$link['id'],'challenge_id'=>$challengeId],$minorUsuarioId);
    return [
        'code'=>$code,
        'expires_minutes'=>$minutes,
        'expires_at'=>$expires,
        'link_id'=>(int)$link['id'],
        'guardian_name'=>(string)($link['guardian_nome']??'responsável'),
    ];
}

function afGuardianVerifyFamilyCode(PDO $pdo, int $guardianUsuarioId, int $linkId, string $code): array
{
    if (!afGuardianTableExists($pdo,'af_guardian_family_challenges')) {
        throw new RuntimeException('Importe a correção de segurança sem terceiros antes de confirmar o código familiar.');
    }
    $code=preg_replace('/\D+/','',$code)??'';
    if(strlen($code)!==8) throw new InvalidArgumentException('Informe o código familiar de 8 dígitos.');

    $st=$pdo->prepare("SELECT l.*,m.nome minor_nome FROM af_guardian_minor_links l JOIN af_usuarios m ON m.id=l.minor_usuario_id
        WHERE l.id=? AND l.guardian_usuario_id=? AND l.status IN ('pending_verification','verified_pending_consent','active') LIMIT 1");
    $st->execute([$linkId,$guardianUsuarioId]);$link=$st->fetch();
    if(!$link) throw new RuntimeException('Vínculo familiar não encontrado.');

    afRateLimitOrFail($pdo,'guardian_family_verify_user',(string)$guardianUsuarioId,10,3600,3600);
    afRateLimitOrFail($pdo,'guardian_family_verify_ip',clientIp(),25,3600,3600);

    $st=$pdo->prepare("SELECT * FROM af_guardian_family_challenges WHERE link_id=? AND status='pending' ORDER BY id DESC LIMIT 1");
    $st->execute([$linkId]);$challenge=$st->fetch();
    if(!$challenge) throw new RuntimeException('Peça ao menor para gerar um novo código familiar.');
    if(strtotime((string)$challenge['expires_at'])<time()){
        $pdo->prepare("UPDATE af_guardian_family_challenges SET status='expired',updated_at=NOW() WHERE id=?")->execute([(int)$challenge['id']]);
        throw new RuntimeException('O código familiar expirou. Gere outro na conta do menor.');
    }
    if((int)$challenge['attempts']>=(int)$challenge['max_attempts']){
        $pdo->prepare("UPDATE af_guardian_family_challenges SET status='blocked',updated_at=NOW() WHERE id=?")->execute([(int)$challenge['id']]);
        throw new RuntimeException('Limite de tentativas atingido. Gere outro código na conta do menor.');
    }
    $expected=hash_hmac('sha256',$code,SECURITY_HASH_SALT.'|guardian-family|'.$linkId);
    if(!hash_equals((string)$challenge['code_hash'],$expected)){
        $pdo->prepare('UPDATE af_guardian_family_challenges SET attempts=attempts+1,updated_at=NOW() WHERE id=?')->execute([(int)$challenge['id']]);
        afLogSeguranca($pdo,'guardian_family_code_invalid',25,['link_id'=>$linkId,'challenge_id'=>(int)$challenge['id']],$guardianUsuarioId);
        throw new RuntimeException('Código familiar incorreto.');
    }

    $pdo->beginTransaction();
    try{
        $pdo->prepare("UPDATE af_guardian_family_challenges SET status='verified',attempts=attempts+1,verified_at=NOW(),verified_ip=?,verified_device_uuid=?,updated_at=NOW() WHERE id=?")
            ->execute([clientIp(),deviceUuid(),(int)$challenge['id']]);
        if(afGuardianColumnExists($pdo,'af_guardian_minor_links','family_confirmed_at')){
            $pdo->prepare('UPDATE af_guardian_minor_links SET family_confirmed_at=NOW(),family_challenge_id=?,atualizado_em=NOW() WHERE id=?')
                ->execute([(int)$challenge['id'],$linkId]);
        }
        if(afGuardianAdultVerified($pdo,$guardianUsuarioId)){
            $pdo->prepare("UPDATE af_guardian_minor_links SET status='verified_pending_consent',verificado_em=COALESCE(verificado_em,NOW()),atualizado_em=NOW() WHERE id=? AND status='pending_verification'")
                ->execute([$linkId]);
        }
        $pdo->commit();
    }catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}

    criarNotificacao($pdo,(int)$link['minor_usuario_id'],'guardian_family_confirmed','Vínculo familiar confirmado','Seu responsável confirmou o código familiar. Os recursos continuam bloqueados até a revisão interna e os consentimentos.');
    afLogSeguranca($pdo,'guardian_family_code_verified',5,['link_id'=>$linkId,'minor_user_id'=>(int)$link['minor_usuario_id']],$guardianUsuarioId);
    if(function_exists('afMinorPolicyClearCache'))afMinorPolicyClearCache((int)$link['minor_usuario_id']);
    return afGuardianVerificationStatus($pdo,$guardianUsuarioId);
}

function afGuardianInternalRiskAssessment(PDO $pdo, int $usuarioId): array
{
    $row=afGuardianEnsureVerification($pdo,$usuarioId);
    $links=afGuardianFamilyLinks($pdo,$usuarioId);
    $score=0;$flags=[];
    $confirmed=0;
    foreach($links as $link){if(!empty($link['family_confirmed_at']))$confirmed++;}

    if(empty($row['declaracao_aceita_em'])||empty($row['data_nascimento_confirmada_em'])){$score+=100;$flags[]='declaration_missing';}
    if(empty($row['email_verificado_em'])){$score+=100;$flags[]='email_not_verified';}
    if($confirmed<1){$score+=100;$flags[]='family_code_not_confirmed';}
    if(count($links)>5){$score+=20;$flags[]='many_dependents';}

    if(!empty($row['data_cadastro']) && strtotime((string)$row['data_cadastro'])>time()-86400){$score+=15;$flags[]='new_guardian_account';}

    try{
        $st=$pdo->prepare("SELECT COUNT(*) FROM af_guardian_family_challenges c JOIN af_guardian_minor_links l ON l.id=c.link_id WHERE l.guardian_usuario_id=? AND c.attempts>=3");
        $st->execute([$usuarioId]);
        if((int)$st->fetchColumn()>0){$score+=20;$flags[]='repeated_family_code_errors';}
    }catch(Throwable $e){}

    try{
        $st=$pdo->prepare("SELECT COUNT(DISTINCT v.guardian_account_id) FROM af_guardian_verifications v WHERE v.device_uuid=? AND v.guardian_account_id<>?");
        $st->execute([(string)($row['device_uuid']??deviceUuid()),(int)($row['guardian_account_id']??0)]);
        if((int)$st->fetchColumn()>0){$score+=25;$flags[]='device_used_by_multiple_guardians';}
    }catch(Throwable $e){}

    foreach($links as $link){
        try{
            $st=$pdo->prepare('SELECT ip_criacao,device_uuid FROM af_guardian_invitations WHERE id=? LIMIT 1');
            $st->execute([(int)($link['invitation_id']??0)]);$invite=$st->fetch();
            if(!$invite)continue;
            if(!empty($invite['device_uuid']) && hash_equals((string)$invite['device_uuid'],(string)($row['device_uuid']??''))){$score+=15;$flags[]='same_device_as_minor_invitation';}
            if(!empty($invite['ip_criacao']) && hash_equals((string)$invite['ip_criacao'],(string)($row['ip_address']??''))){$score+=5;$flags[]='same_ip_as_minor_invitation';}
        }catch(Throwable $e){}
    }

    $flags=array_values(array_unique($flags));
    return [
        'score'=>min(999,$score),
        'flags'=>$flags,
        'confirmed_links'=>$confirmed,
        'total_links'=>count($links),
        'automatic_approval'=>false,
        'requires_manual_review'=>true,
    ];
}

function afGuardianSubmitInternalReview(PDO $pdo, int $usuarioId): array
{
    if(!afGuardianTableExists($pdo,'af_guardian_manual_reviews')){
        throw new RuntimeException('Importe a correção de segurança sem terceiros antes de enviar para revisão.');
    }
    $status=afGuardianVerificationStatus($pdo,$usuarioId);
    if($status['approved'])return $status;
    if(!$status['declaration_ok'])throw new RuntimeException('Confirme a declaração de responsabilidade.');
    if(!$status['email_ok'])throw new RuntimeException('Confirme o e-mail.');
    if(!$status['family_ok'])throw new RuntimeException('Confirme pelo menos um código familiar gerado na conta do menor.');

    $risk=afGuardianInternalRiskAssessment($pdo,$usuarioId);
    $pdo->beginTransaction();
    try{
        $pdo->prepare("UPDATE af_guardian_manual_reviews SET status='cancelled',updated_at=NOW() WHERE guardian_account_id=? AND status IN ('pending','needs_info')")
            ->execute([$status['account_id']]);
        $st=$pdo->prepare("INSERT INTO af_guardian_manual_reviews
            (guardian_account_id,verification_id,status,risk_score,risk_flags_json,submitted_at,request_ip,request_device_uuid,created_at,updated_at)
            VALUES (?,?,'pending',?,?,NOW(),?,?,NOW(),NOW())");
        $st->execute([$status['account_id'],$status['verification_id'],(int)$risk['score'],json_encode($risk['flags'],JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),clientIp(),deviceUuid()]);
        $reviewId=(int)$pdo->lastInsertId();
        $pdo->prepare("UPDATE af_guardian_verifications SET metodo='internal_layered_manual_review',status='review',resultado='pending_internal_review',score_risco=?,motivo_rejeicao=NULL,atualizado_em=NOW() WHERE id=?")
            ->execute([(int)$risk['score'],$status['verification_id']]);
        $pdo->prepare("UPDATE af_guardian_accounts SET status_verificacao='pending',metodo_verificacao='internal_layered_manual_review',verificado_em=NULL,atualizado_em=NOW() WHERE id=?")
            ->execute([$status['account_id']]);
        $pdo->commit();
    }catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}

    criarNotificacao($pdo,$usuarioId,'guardian_review_submitted','Verificação enviada para análise','Sua solicitação foi enviada para revisão interna. Nenhum recurso do menor será liberado antes da aprovação e dos consentimentos.');
    afLogSeguranca($pdo,'guardian_internal_review_submitted',10,['review_id'=>$reviewId,'risk_score'=>$risk['score'],'flags'=>$risk['flags']],$usuarioId);
    return afGuardianVerificationStatus($pdo,$usuarioId);
}

function afGuardianAdminReviewList(PDO $pdo, string $status='pending', int $limit=100): array
{
    if(!afGuardianTableExists($pdo,'af_guardian_manual_reviews'))return [];
    $allowed=['pending','approved','rejected','needs_info','expired','all'];
    if(!in_array($status,$allowed,true))$status='pending';
    $where=$status==='all'?'1=1':'r.status=?';
    $params=$status==='all'?[]:[$status];
    $sql="SELECT r.*,ga.usuario_id,ga.status_verificacao,u.nome,u.email,u.aura_id,u.data_cadastro,
            a.data_nascimento,a.idade_declarada,
            (SELECT COUNT(*) FROM af_guardian_minor_links l WHERE l.guardian_usuario_id=ga.usuario_id AND l.status IN ('pending_verification','verified_pending_consent','active')) dependent_count,
            (SELECT COUNT(*) FROM af_guardian_minor_links l WHERE l.guardian_usuario_id=ga.usuario_id AND l.family_confirmed_at IS NOT NULL AND l.status IN ('pending_verification','verified_pending_consent','active')) confirmed_count
        FROM af_guardian_manual_reviews r
        JOIN af_guardian_accounts ga ON ga.id=r.guardian_account_id
        JOIN af_usuarios u ON u.id=ga.usuario_id
        LEFT JOIN af_user_age_profiles a ON a.usuario_id=u.id
        WHERE {$where} ORDER BY FIELD(r.status,'pending','needs_info','approved','rejected','expired'),r.submitted_at ASC LIMIT ".max(1,min(500,$limit));
    $st=$pdo->prepare($sql);$st->execute($params);return $st->fetchAll()?:[];
}

function afGuardianAdminReviewDecision(PDO $pdo, int $reviewId, int $adminId, string $decision, string $notes='', array $reviewData=[]): array
{
    if(!afGuardianTableExists($pdo,'af_guardian_manual_reviews'))throw new RuntimeException('Tabela de revisão interna não instalada.');
    $decision=strtolower(trim($decision));
    if(!in_array($decision,['approve','reject','needs_info'],true))throw new InvalidArgumentException('Decisão inválida.');
    $notes=mb_substr(trim($notes),0,2000);
    $method=trim((string)($reviewData['review_method']??''));
    $checklist=[];
    foreach(afGuardianReviewChecklistKeys() as $key=>$label)$checklist[$key]=!empty($reviewData[$key]);
    $identityFingerprint=null;

    $st=$pdo->prepare("SELECT r.*,ga.usuario_id,ga.id account_id,v.id verification_id FROM af_guardian_manual_reviews r
        JOIN af_guardian_accounts ga ON ga.id=r.guardian_account_id
        JOIN af_guardian_verifications v ON v.id=r.verification_id
        WHERE r.id=? LIMIT 1");
    $st->execute([$reviewId]);$review=$st->fetch();
    if(!$review)throw new RuntimeException('Revisão não encontrada.');
    if(!in_array((string)$review['status'],['pending','needs_info'],true))throw new RuntimeException('Esta revisão já foi encerrada.');
    $guardianId=(int)$review['usuario_id'];

    $verificationStatus=afGuardianVerificationStatus($pdo,$guardianId);
    if($decision==='approve'){
        if(!$verificationStatus['declaration_ok']||!$verificationStatus['email_ok']||!$verificationStatus['family_ok']){
            throw new RuntimeException('Os requisitos internos deixaram de ser válidos. Não é possível aprovar.');
        }
        if(!array_key_exists($method,afGuardianReviewMethods())){
            throw new RuntimeException('Selecione conferência presencial ou conferência ao vivo sem gravação.');
        }
        foreach($checklist as $key=>$checked){
            if(!$checked)throw new RuntimeException('Marque todo o checklist obrigatório antes de aprovar.');
        }
        if(mb_strlen($notes)<20)throw new RuntimeException('Registre uma observação de aprovação com pelo menos 20 caracteres.');
        $fingerprintRequired=filter_var(afGuardianVerificationConfig($pdo,'guardian_identity_fingerprint_required','1'),FILTER_VALIDATE_BOOL);
        if($fingerprintRequired){
            $identityFingerprint=afGuardianIdentityFingerprint((string)($reviewData['document_number']??''));
            $dup=$pdo->prepare("SELECT r.id,ga.usuario_id FROM af_guardian_manual_reviews r JOIN af_guardian_accounts ga ON ga.id=r.guardian_account_id WHERE r.identity_fingerprint=? AND r.guardian_account_id<>? AND r.status='approved' AND (r.valid_until IS NULL OR r.valid_until>NOW()) LIMIT 1");
            $dup->execute([$identityFingerprint,(int)$review['account_id']]);
            if($dup->fetch())throw new RuntimeException('Este documento já está associado a outro responsável aprovado. Encaminhe para análise de segurança.');
        }
    }

    $validDays=max(30,min(730,(int)afGuardianVerificationConfig($pdo,'guardian_internal_review_valid_days','365')));
    $newStatus=$decision==='approve'?'approved':($decision==='reject'?'rejected':'needs_info');
    $validUntil=$decision==='approve'?(new DateTimeImmutable('now',new DateTimeZone(APP_TIMEZONE)))->modify('+'.$validDays.' days')->format('Y-m-d H:i:s'):null;
    $protocol=$decision==='approve'?'AF-GUARD-'.date('Ymd').'-'.$reviewId.'-'.strtoupper(bin2hex(random_bytes(3))):null;
    $checklistJson=$decision==='approve'?json_encode($checklist,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES):null;

    $pdo->beginTransaction();
    try{
        $pdo->prepare('UPDATE af_guardian_manual_reviews SET status=?,reviewer_admin_id=?,review_method=?,reviewer_checklist_json=?,identity_fingerprint=?,review_protocol=?,reviewer_notes=?,reviewed_at=NOW(),valid_until=?,updated_at=NOW() WHERE id=?')
            ->execute([$newStatus,$adminId,$method?:null,$checklistJson,$identityFingerprint,$protocol,$notes?:null,$validUntil,$reviewId]);
        if($decision==='approve'){
            $pdo->prepare("UPDATE af_guardian_verifications SET status='approved',resultado='adult_verified_internal_review',adulto_verificado_em=NOW(),metodo='internal_layered_manual_review',motivo_rejeicao=NULL,atualizado_em=NOW() WHERE id=?")
                ->execute([(int)$review['verification_id']]);
            $pdo->prepare("UPDATE af_guardian_accounts SET status_verificacao='verified',metodo_verificacao='internal_layered_manual_review',verificado_em=NOW(),atualizado_em=NOW() WHERE id=?")
                ->execute([(int)$review['account_id']]);
            $pdo->prepare("UPDATE af_user_age_profiles SET tipo_conta='guardian',status_idade='guardian_verified',verificado_em=NOW(),atualizado_em=NOW() WHERE usuario_id=?")
                ->execute([$guardianId]);
            $pdo->prepare("UPDATE af_guardian_minor_links SET status='verified_pending_consent',verificado_em=COALESCE(verificado_em,NOW()),atualizado_em=NOW() WHERE guardian_usuario_id=? AND family_confirmed_at IS NOT NULL AND status='pending_verification'")
                ->execute([$guardianId]);
        }elseif($decision==='reject'){
            $pdo->prepare("UPDATE af_guardian_verifications SET status='rejected',resultado='internal_review_rejected',motivo_rejeicao=?,adulto_verificado_em=NULL,atualizado_em=NOW() WHERE id=?")
                ->execute([$notes?:'Revisão interna não aprovada',(int)$review['verification_id']]);
            $pdo->prepare("UPDATE af_guardian_accounts SET status_verificacao='rejected',verificado_em=NULL,atualizado_em=NOW() WHERE id=?")
                ->execute([(int)$review['account_id']]);
            $pdo->prepare("UPDATE af_guardian_minor_links SET status='pending_verification',verificado_em=NULL,atualizado_em=NOW() WHERE guardian_usuario_id=? AND status IN ('verified_pending_consent','active')")
                ->execute([$guardianId]);
        }else{
            $pdo->prepare("UPDATE af_guardian_verifications SET status='review',resultado='needs_information',motivo_rejeicao=?,adulto_verificado_em=NULL,atualizado_em=NOW() WHERE id=?")
                ->execute([$notes?:'Informações adicionais solicitadas',(int)$review['verification_id']]);
            $pdo->prepare("UPDATE af_guardian_accounts SET status_verificacao='pending',verificado_em=NULL,atualizado_em=NOW() WHERE id=?")
                ->execute([(int)$review['account_id']]);
        }
        $pdo->prepare('INSERT INTO af_age_status_history
            (usuario_id,status_anterior,status_novo,motivo,actor_usuario_id,dados,criado_em)
            VALUES (?,?,?,?,?,?,NOW())')->execute([
                $guardianId,(string)($verificationStatus['approved']?'guardian_verified':'adult_verified'),
                $decision==='approve'?'guardian_verified':'adult_verified',
                'decisão da revisão interna do responsável',null,
                json_encode(['review_id'=>$reviewId,'admin_id'=>$adminId,'decision'=>$decision,'method'=>$method?:null,'protocol'=>$protocol,'valid_until'=>$validUntil],JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)
            ]);
        $pdo->commit();
    }catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}

    $title=$decision==='approve'?'Responsável verificado':($decision==='reject'?'Verificação não aprovada':'Informações adicionais necessárias');
    $message=$decision==='approve'
        ? 'Sua verificação interna foi aprovada. Cada menor continua protegido até consentimentos específicos e demais controles.'
        : ($notes!==''?$notes:'Consulte a área de verificação para continuar.');
    criarNotificacao($pdo,$guardianId,'guardian_internal_review_'.$newStatus,$title,$message);
    foreach(afGuardianDependentes($pdo,$guardianId) as $dependent){
        criarNotificacao($pdo,(int)$dependent['minor_usuario_id'],'guardian_internal_review_'.$newStatus,$title,$decision==='approve'?'Seu responsável foi verificado. Os recursos continuam sujeitos aos consentimentos e à política de segurança.':'Os recursos permanecem bloqueados.');
        if(function_exists('afMinorPolicyClearCache'))afMinorPolicyClearCache((int)$dependent['minor_usuario_id']);
    }
    afLogSeguranca($pdo,'guardian_internal_review_'.$newStatus,$decision==='approve'?5:40,['review_id'=>$reviewId,'admin_id'=>$adminId,'method'=>$method?:null,'protocol'=>$protocol],$guardianId);
    return afGuardianVerificationStatus($pdo,$guardianId);
}

function afGuardianVerificationStatus(PDO $pdo, int $usuarioId): array
{
    $row = afGuardianEnsureVerification($pdo, $usuarioId);
    $declarationOk = !empty($row['declaracao_aceita_em']) && !empty($row['data_nascimento_confirmada_em']);
    $emailOk = !empty($row['email_verificado_em']);
    $links = afGuardianFamilyLinks($pdo,$usuarioId);
    $confirmed = 0;
    foreach($links as $link){if(!empty($link['family_confirmed_at']))$confirmed++;}
    $familyOk = $confirmed > 0;
    $review = afGuardianLatestInternalReview($pdo,$usuarioId);
    $reviewStatus=(string)($review['status']??'not_submitted');
    $approved = (string)($row['status_verificacao'] ?? '') === 'verified'
        && !empty($row['verificado_em'])
        && afGuardianInternalReviewValid($pdo,$usuarioId);

    $next='declaration';
    if($declarationOk&&!$emailOk)$next='email';
    elseif($declarationOk&&$emailOk&&!$familyOk)$next='family';
    elseif($declarationOk&&$emailOk&&$familyOk&&!$approved&&in_array($reviewStatus,['not_submitted','rejected','expired','cancelled'],true))$next='review';
    elseif($declarationOk&&$emailOk&&$familyOk&&!$approved&&in_array($reviewStatus,['pending','needs_info'],true))$next='waiting';
    elseif($approved)$next='completed';

    return [
        'account_id'=>(int)($row['guardian_account_id'] ?? 0),
        'verification_id'=>(int)($row['id'] ?? 0),
        'status'=>(string)($row['status_verificacao'] ?? 'pending'),
        'declaration_ok'=>$declarationOk,
        'email_ok'=>$emailOk,
        'phone_ok'=>false,
        'phone_required'=>false,
        'sms_available'=>false,
        'family_ok'=>$familyOk,
        'family_confirmed_count'=>$confirmed,
        'family_total_count'=>count($links),
        'family_links'=>$links,
        'review'=>$review,
        'review_status'=>$reviewStatus,
        'review_pending'=>$reviewStatus==='pending',
        'review_needs_info'=>$reviewStatus==='needs_info',
        'approved'=>$approved,
        'professional'=>['required'=>false,'available'=>false,'verified'=>false,'provider'=>null],
        'professional_required'=>false,
        'professional_available'=>false,
        'professional_ok'=>false,
        'next_step'=>$next,
        'email_masked'=>afGuardianMaskEmail((string)($row['email'] ?? '')),
        'phone_masked'=>!empty($row['telefone']) ? afGuardianMaskPhone((string)$row['telefone']) : null,
        'verified_at'=>$row['verificado_em'] ?? null,
        'row'=>$row,
    ];
}

function afGuardianSaveAdultDeclaration(
    PDO $pdo,
    int $usuarioId,
    string $dataNascimento,
    bool $declaresAdult,
    bool $declaresResponsibility
): array {
    if (!$declaresAdult || !$declaresResponsibility) {
        throw new InvalidArgumentException('Confirme as duas declarações para continuar.');
    }
    $age = afResumoIdade($pdo, $usuarioId);
    if (!$age['completo'] || (int)($age['idade'] ?? 0) < 18) {
        throw new RuntimeException('Esta conta não está classificada como maior de 18 anos.');
    }
    if ((string)$age['data_nascimento'] !== $dataNascimento) {
        throw new InvalidArgumentException('A data de nascimento não corresponde à registrada na conta.');
    }

    $verification = afGuardianEnsureVerification($pdo, $usuarioId);
    $text = 'Declaro ser maior de 18 anos, conhecer o menor vinculado e possuir responsabilidade legal para representá-lo. Declaro que as informações fornecidas são verdadeiras e estou ciente de que informações falsas poderão resultar em bloqueio e registro de auditoria.';
    $version=(string)afGuardianVerificationConfig($pdo,'guardian_declaration_version','2.0');
    $hash = hash('sha256', $version . '|' . $text);

    $pdo->prepare('UPDATE af_guardian_verifications
        SET data_nascimento_confirmada=?,data_nascimento_confirmada_em=NOW(),declaration_version=?,declaration_text_hash=?,declaracao_aceita_em=NOW(),
            ip_address=?,user_agent=?,device_uuid=?,metodo=\'internal_layered_manual_review\',status=IF(status=\'approved\',status,\'pending\'),atualizado_em=NOW()
        WHERE id=?')
        ->execute([
            $dataNascimento,$version,$hash,clientIp(),substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''),0,1000),deviceUuid(),(int)$verification['id']
        ]);
    $pdo->prepare('UPDATE af_guardian_accounts
        SET data_nascimento_confirmada=?,declaracao_aceita_em=NOW(),metodo_verificacao=\'internal_layered_manual_review\',atualizado_em=NOW()
        WHERE usuario_id=?')->execute([$dataNascimento,$usuarioId]);

    $pdo->prepare('INSERT INTO af_verification_attempts
        (guardian_account_id,verification_id,canal,status,destino_mascarado,ip_address,device_uuid,criado_em,atualizado_em)
        VALUES (?,?,\'declaration\',\'verified\',\'declaração legal\',?,?,NOW(),NOW())')
        ->execute([(int)$verification['guardian_account_id'],(int)$verification['id'],clientIp(),deviceUuid()]);

    afLogSeguranca($pdo, 'guardian_declaration_accepted', 10, ['verification_id'=>(int)$verification['id'],'version'=>$version], $usuarioId);
    return afGuardianVerificationStatus($pdo, $usuarioId);
}

function afGuardianSendVerificationCode(PDO $pdo, int $usuarioId, string $channel): array
{
    $channel = strtolower(trim($channel));
    if ($channel !== 'email') {
        throw new RuntimeException('A verificação por telefone foi removida. Use o código por e-mail e o código familiar.');
    }
    $status = afGuardianVerificationStatus($pdo, $usuarioId);
    $row = $status['row'];
    if (!$status['declaration_ok']) {
        throw new RuntimeException('Confirme primeiro a declaração de maioridade e responsabilidade.');
    }

    $destination = strtolower((string)$row['email']);
    $masked = afGuardianMaskEmail($destination);
    afRateLimitOrFail($pdo, 'guardian_verify_email_user', (string)$usuarioId, 4, 3600, 3600);
    afRateLimitOrFail($pdo, 'guardian_verify_email_ip', clientIp(), 12, 3600, 3600);

    $code = (string)random_int(100000, 999999);
    $hash = hash_hmac('sha256', $code, SECURITY_HASH_SALT.'|guardian|'.$status['account_id'].'|email');
    $minutes = max(5, min(30, (int)afGuardianVerificationConfig($pdo, 'guardian_code_expiration_minutes', '10')));
    $expires = (new DateTimeImmutable('now', new DateTimeZone(APP_TIMEZONE)))
        ->modify('+'.$minutes.' minutes')->format('Y-m-d H:i:s');

    $pdo->prepare("UPDATE af_verification_attempts SET status='superseded',atualizado_em=NOW()
        WHERE guardian_account_id=? AND canal='email' AND status='pending'")->execute([$status['account_id']]);
    $st = $pdo->prepare('INSERT INTO af_verification_attempts
        (guardian_account_id,verification_id,canal,status,destino_mascarado,code_hash,tentativas,max_tentativas,expira_em,ip_address,device_uuid,criado_em,atualizado_em)
        VALUES (?,?,\'email\',\'pending\',?,?,0,5,?,?,?,NOW(),NOW())');
    $st->execute([$status['account_id'],$status['verification_id'],$masked,$hash,$expires,clientIp(),deviceUuid()]);
    $attemptId = (int)$pdo->lastInsertId();

    $html = '<div style="font-family:Arial,sans-serif;max-width:520px;margin:auto;background:#080b14;color:#fff;padding:28px;border-radius:18px">'
        .'<h2 style="color:#36d8ff">AURA FARMING</h2><p>Use este código para confirmar seu e-mail como responsável:</p>'
        .'<div style="font-size:36px;font-weight:900;letter-spacing:8px;text-align:center;padding:18px;background:#11182a;border-radius:12px">'.esc($code).'</div>'
        .'<p style="color:#9aa5b9">O código expira em '.$minutes.' minutos. Não compartilhe com terceiros.</p></div>';
    $sent = enviarEmailSimples($destination, 'Código de verificação do responsável', $html);

    if (!$sent) {
        $pdo->prepare("UPDATE af_verification_attempts SET status='delivery_failed',atualizado_em=NOW() WHERE id=?")->execute([$attemptId]);
        throw new RuntimeException('Não foi possível enviar o código por e-mail. Confira a configuração de e-mail do servidor.');
    }

    afLogSeguranca($pdo, 'guardian_verification_code_sent', 10, ['channel'=>'email','attempt_id'=>$attemptId], $usuarioId);
    $response = ['sent'=>true,'channel'=>'email','destination'=>$masked,'expires_minutes'=>$minutes];
    if (defined('APP_DEBUG') && APP_DEBUG && defined('GUARDIAN_VERIFICATION_DEBUG_CODES') && GUARDIAN_VERIFICATION_DEBUG_CODES) {
        $response['debug_code'] = $code;
    }
    return $response;
}

function afGuardianVerifyCode(PDO $pdo, int $usuarioId, string $channel, string $code): array
{
    $channel = strtolower(trim($channel));
    $code = preg_replace('/\D+/', '', $code) ?? '';
    if ($channel !== 'email' || strlen($code) !== 6) {
        throw new InvalidArgumentException('Informe o código de e-mail com 6 dígitos.');
    }
    $status = afGuardianVerificationStatus($pdo, $usuarioId);
    $st = $pdo->prepare("SELECT * FROM af_verification_attempts
        WHERE guardian_account_id=? AND canal='email' AND status='pending'
        ORDER BY id DESC LIMIT 1");
    $st->execute([$status['account_id']]);
    $attempt = $st->fetch();
    if (!$attempt) throw new RuntimeException('Solicite um novo código antes de confirmar.');
    if (strtotime((string)$attempt['expira_em']) < time()) {
        $pdo->prepare("UPDATE af_verification_attempts SET status='expired',atualizado_em=NOW() WHERE id=?")->execute([(int)$attempt['id']]);
        throw new RuntimeException('Este código expirou. Solicite um novo.');
    }
    if ((int)$attempt['tentativas'] >= (int)$attempt['max_tentativas']) {
        $pdo->prepare("UPDATE af_verification_attempts SET status='blocked',atualizado_em=NOW() WHERE id=?")->execute([(int)$attempt['id']]);
        throw new RuntimeException('Limite de tentativas atingido. Solicite outro código.');
    }

    $expected = hash_hmac('sha256', $code, SECURITY_HASH_SALT.'|guardian|'.$status['account_id'].'|email');
    if (!hash_equals((string)$attempt['code_hash'], $expected)) {
        $pdo->prepare('UPDATE af_verification_attempts SET tentativas=tentativas+1,atualizado_em=NOW() WHERE id=?')->execute([(int)$attempt['id']]);
        afLogSeguranca($pdo, 'guardian_verification_code_invalid', 20, ['channel'=>'email','attempt_id'=>(int)$attempt['id']], $usuarioId);
        throw new RuntimeException('Código incorreto.');
    }

    $pdo->beginTransaction();
    try {
        $pdo->prepare("UPDATE af_verification_attempts SET status='verified',verificado_em=NOW(),tentativas=tentativas+1,atualizado_em=NOW() WHERE id=?")
            ->execute([(int)$attempt['id']]);
        $pdo->prepare('UPDATE af_guardian_verifications SET email_verificado_em=NOW(),atualizado_em=NOW() WHERE id=?')->execute([$status['verification_id']]);
        $pdo->prepare('UPDATE af_guardian_accounts SET email_verificado_em=NOW(),atualizado_em=NOW() WHERE id=?')->execute([$status['account_id']]);
        $pdo->commit();
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        throw $e;
    }

    afLogSeguranca($pdo, 'guardian_verification_code_approved', 5, ['channel'=>'email'], $usuarioId);
    return afGuardianVerificationStatus($pdo, $usuarioId);
}

/**
 * Por compatibilidade, "finalizar" agora envia para revisão interna manual.
 * A conta não é aprovada automaticamente.
 */
function afGuardianFinalizeAdultVerification(PDO $pdo, int $usuarioId): array
{
    return afGuardianSubmitInternalReview($pdo,$usuarioId);
}

/** Telefone é apenas contato opcional e não altera a verificação. */
function afGuardianUpdatePhone(PDO $pdo, int $usuarioId, string $phone): array
{
    $normalized = afGuardianNormalizePhone($phone);
    afGuardianGarantirConta($pdo, $usuarioId, $normalized !== '' ? $normalized : null, 'optional_contact_update');
    $pdo->prepare('UPDATE af_guardian_accounts SET telefone=?,telefone_verificado_em=NULL,atualizado_em=NOW() WHERE usuario_id=?')
        ->execute([$normalized !== '' ? $normalized : null,$usuarioId]);
    afLogSeguranca($pdo, 'guardian_optional_phone_updated', 5, ['phone_masked'=>$normalized!==''?afGuardianMaskPhone($normalized):null], $usuarioId);
    return afGuardianVerificationStatus($pdo, $usuarioId);
}
