<?php
/**
 * AURA FARMING — Etapa 17
 * Consentimentos parentais específicos, versionados e revogáveis.
 *
 * Esta etapa registra as permissões do responsável, mas NÃO libera por si só
 * câmera, Farm, Battle, live ou compartilhamento para menores. As políticas
 * de segurança e a câmera protegida serão aplicadas nas etapas seguintes.
 */

function afConsentDefinitions(): array
{
    return [
        'account_maintenance' => [
            'label' => 'Criação e manutenção da conta',
            'description' => 'Autoriza manter a conta do menor e os dados essenciais de cadastro.',
            'required' => true,
            'group' => 'essential',
        ],
        'camera_motion_detection' => [
            'label' => 'Uso da câmera para detectar movimentos',
            'description' => 'Autoriza o uso da câmera durante a partida para reconhecer o corpo e os movimentos.',
            'required' => false,
            'group' => 'camera',
        ],
        'body_movement_processing' => [
            'label' => 'Processamento corporal para gerar pontuação',
            'description' => 'Autoriza processar poses, gestos e métricas corporais para calcular Aura e combos.',
            'required' => false,
            'group' => 'camera',
        ],
        'individual_farm' => [
            'label' => 'Participação em partidas individuais',
            'description' => 'Autoriza o menor a participar do modo Farm individual quando as proteções técnicas estiverem concluídas.',
            'required' => false,
            'group' => 'gameplay',
        ],
        'ranking_alias' => [
            'label' => 'Ranking usando somente apelido e AURA-ID',
            'description' => 'Autoriza exibir apenas o apelido, avatar protegido e pontuação no ranking.',
            'required' => false,
            'group' => 'social',
        ],
        'approved_contacts_battle' => [
            'label' => 'Partidas com contatos aprovados',
            'description' => 'Autoriza Battle apenas com pessoas previamente aprovadas pelo responsável.',
            'required' => false,
            'group' => 'social',
        ],
        'guardian_notifications' => [
            'label' => 'Notificações de segurança ao responsável',
            'description' => 'Autoriza o envio de alertas sobre partidas, convites, denúncias e alterações de privacidade.',
            'required' => false,
            'group' => 'notifications',
        ],
    ];
}

function afConsentHighRiskDefinitions(): array
{
    return [
        'public_live' => ['label'=>'Transmissão pública','description'=>'Permanece desativada para menores.'],
        'stranger_messages' => ['label'=>'Mensagens de desconhecidos','description'=>'Permanece desativada para menores.'],
        'real_video_replay' => ['label'=>'Replay com imagem real','description'=>'Permanece desativado para menores.'],
        'video_download' => ['label'=>'Download de vídeo','description'=>'Permanece desativado para menores.'],
        'public_location' => ['label'=>'Localização pública','description'=>'Permanece desativada para menores.'],
        'full_public_profile' => ['label'=>'Perfil público completo','description'=>'Permanece desativado para menores.'],
    ];
}

function afConsentConfig(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 afConsentCurrentVersion(PDO $pdo): array
{
    $wanted = (string)afConsentConfig($pdo, 'parental_consent_current_version', '1.0');
    $st = $pdo->prepare('SELECT * FROM af_consent_versions WHERE version_key=? AND ativo=1 LIMIT 1');
    $st->execute([$wanted]);
    $version = $st->fetch();
    if (!$version) {
        $st = $pdo->query('SELECT * FROM af_consent_versions WHERE ativo=1 ORDER BY vigencia_em DESC,id DESC LIMIT 1');
        $version = $st ? $st->fetch() : false;
    }
    if (!$version) throw new RuntimeException('A versão do consentimento parental não foi instalada no banco.');
    return $version;
}

function afConsentGetLink(PDO $pdo, int $guardianUsuarioId, int $linkId): array
{
    $st = $pdo->prepare("SELECT l.*,m.nome minor_nome,m.username minor_username,m.aura_id minor_aura_id,
            m.foto_perfil minor_foto_perfil,m.foto_externa minor_foto_externa,
            a.idade_declarada,a.status_idade,p.perfil_privado,
            ga.status_verificacao guardian_status,ga.verificado_em guardian_verificado_em
        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
        LEFT JOIN af_perfis p ON p.usuario_id=m.id
        LEFT JOIN af_guardian_accounts ga ON ga.usuario_id=l.guardian_usuario_id
        WHERE l.id=? AND l.guardian_usuario_id=?
          AND l.status IN ('verified_pending_consent','active') LIMIT 1");
    $st->execute([$linkId,$guardianUsuarioId]);
    $link = $st->fetch();
    if (!$link) throw new RuntimeException('Vínculo do dependente não encontrado ou ainda não verificado.');
    if ((string)($link['guardian_status'] ?? '') !== 'verified' || empty($link['guardian_verificado_em'])
        || !function_exists('afGuardianAdultVerified') || !afGuardianAdultVerified($pdo,$guardianUsuarioId)) {
        throw new RuntimeException('Conclua primeiro a verificação interna do responsável.');
    }
    if (!function_exists('afGuardianFamilyLinkConfirmed') || !afGuardianFamilyLinkConfirmed($pdo,(int)$link['id'])) {
        throw new RuntimeException('Confirme primeiro o código familiar gerado na conta do menor.');
    }
    return $link;
}

function afConsentCurrentForLink(PDO $pdo, int $linkId): ?array
{
    $st = $pdo->prepare('SELECT c.*,v.version_key,v.titulo version_title,v.resumo version_summary
        FROM af_parental_consents c
        JOIN af_consent_versions v ON v.id=c.consent_version_id
        WHERE c.link_id=? AND c.status=\'active\'
        ORDER BY c.id DESC LIMIT 1');
    $st->execute([$linkId]);
    $consent = $st->fetch();
    if (!$consent) return null;

    $st = $pdo->prepare('SELECT permission_key,permitido,obrigatorio,confirmado_em,revogado_em
        FROM af_consent_permissions WHERE consent_id=? ORDER BY id');
    $st->execute([(int)$consent['id']]);
    $permissions = [];
    foreach ($st->fetchAll() as $row) {
        $permissions[(string)$row['permission_key']] = [
            'allowed'=>(bool)$row['permitido'],
            'required'=>(bool)$row['obrigatorio'],
            'confirmed_at'=>$row['confirmado_em'] ?? null,
            'revoked_at'=>$row['revogado_em'] ?? null,
        ];
    }
    $consent['permissions'] = $permissions;
    return $consent;
}

function afConsentAudit(PDO $pdo, int $linkId, int $actorUsuarioId, string $action, array $data = [], ?int $consentId = null): void
{
    $pdo->prepare('INSERT INTO af_consent_audit_logs
        (consent_id,link_id,actor_usuario_id,action_key,dados,ip_address,user_agent,device_uuid,criado_em)
        VALUES (?,?,?,?,?,?,?,?,NOW())')->execute([
            $consentId ?: null,$linkId,$actorUsuarioId,substr($action,0,60),
            $data ? json_encode($data,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) : null,
            clientIp(),substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''),0,1000),deviceUuid()
        ]);
}

function afConsentNormalizePermissions(array $input): array
{
    $definitions = afConsentDefinitions();
    $normalized = [];
    foreach ($definitions as $key=>$definition) {
        $normalized[$key] = !empty($input[$key]);
        if (!empty($definition['required'])) $normalized[$key] = true;
    }

    if ($normalized['individual_farm']) {
        $normalized['camera_motion_detection'] = true;
        $normalized['body_movement_processing'] = true;
    }
    if ($normalized['approved_contacts_battle']) {
        $normalized['individual_farm'] = true;
        $normalized['camera_motion_detection'] = true;
        $normalized['body_movement_processing'] = true;
    }
    ksort($normalized);
    return $normalized;
}

function afConsentSave(PDO $pdo, int $guardianUsuarioId, int $linkId, array $permissions, bool $confirmedSpecific): array
{
    if (!$confirmedSpecific) {
        throw new InvalidArgumentException('Confirme que cada autorização foi analisada individualmente.');
    }
    if (!afGuardianAdultVerified($pdo,$guardianUsuarioId)) {
        throw new RuntimeException('Somente um responsável adulto verificado pode registrar consentimentos.');
    }
    $link = afConsentGetLink($pdo,$guardianUsuarioId,$linkId);
    $version = afConsentCurrentVersion($pdo);
    $ageBefore = afBuscarPerfilIdade($pdo,(int)$link['minor_usuario_id']);
    $previousAgeStatus = (string)($ageBefore['status_idade'] ?? 'minor_pending_guardian');
    $normalized = afConsentNormalizePermissions($permissions);
    if (empty($normalized['account_maintenance'])) {
        throw new InvalidArgumentException('A manutenção da conta é necessária para manter o vínculo ativo.');
    }

    $allStored = $normalized;
    foreach (array_keys(afConsentHighRiskDefinitions()) as $key) $allStored[$key] = false;
    ksort($allStored);
    $permissionJson = json_encode($allStored,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    $permissionsHash = hash('sha256',(string)$permissionJson);
    $termsHash = (string)$version['content_hash'];

    $pdo->beginTransaction();
    try {
        $old = afConsentCurrentForLink($pdo,$linkId);
        if ($old) {
            $pdo->prepare("UPDATE af_parental_consents SET status='superseded',atualizado_em=NOW() WHERE id=?")
                ->execute([(int)$old['id']]);
            $pdo->prepare('UPDATE af_consent_permissions SET revogado_em=NOW(),atualizado_em=NOW() WHERE consent_id=? AND revogado_em IS NULL')
                ->execute([(int)$old['id']]);
        }

        $st = $pdo->prepare('INSERT INTO af_parental_consents
            (link_id,guardian_usuario_id,minor_usuario_id,consent_version_id,status,confirmation_method,terms_hash,permissions_hash,
             aceito_em,ip_address,user_agent,device_uuid,criado_em,atualizado_em)
            VALUES (?,?,?,?,\'active\',\'verified_guardian_session\',?,?,NOW(),?,?,?,NOW(),NOW())');
        $st->execute([
            $linkId,$guardianUsuarioId,(int)$link['minor_usuario_id'],(int)$version['id'],$termsHash,$permissionsHash,
            clientIp(),substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''),0,1000),deviceUuid()
        ]);
        $consentId = (int)$pdo->lastInsertId();

        $definitions = afConsentDefinitions();
        $insert = $pdo->prepare('INSERT INTO af_consent_permissions
            (consent_id,permission_key,permitido,obrigatorio,confirmado_em,criado_em,atualizado_em)
            VALUES (?,?,?,?,NOW(),NOW(),NOW())');
        foreach ($allStored as $key=>$allowed) {
            $required = isset($definitions[$key]) && !empty($definitions[$key]['required']);
            $insert->execute([$consentId,$key,$allowed?1:0,$required?1:0]);
        }

        $pdo->prepare("UPDATE af_guardian_minor_links
            SET status='active',atualizado_em=NOW() WHERE id=?")
            ->execute([$linkId]);
        $pdo->prepare("UPDATE af_user_age_profiles
            SET status_idade='minor_authorized',atualizado_em=NOW() WHERE usuario_id=? AND tipo_conta='minor'")
            ->execute([(int)$link['minor_usuario_id']]);
        $pdo->prepare('UPDATE af_perfis SET perfil_privado=1,atualizado_em=NOW() WHERE usuario_id=?')
            ->execute([(int)$link['minor_usuario_id']]);
        $pdo->prepare('INSERT INTO af_age_status_history
            (usuario_id,status_anterior,status_novo,motivo,actor_usuario_id,dados,criado_em)
            VALUES (?,?,\'minor_authorized\',\'consentimentos parentais específicos registrados\',?,?,NOW())')
            ->execute([
                (int)$link['minor_usuario_id'],$previousAgeStatus,$guardianUsuarioId,
                json_encode(['consent_id'=>$consentId,'version'=>(string)$version['version_key'],'permissions'=>$normalized],JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)
            ]);

        afConsentAudit($pdo,$linkId,$guardianUsuarioId,$old?'consent_updated':'consent_accepted',[
            'version'=>(string)$version['version_key'],'permissions'=>$normalized,'high_risk_locked'=>array_keys(afConsentHighRiskDefinitions())
        ],$consentId);

        criarNotificacao($pdo,(int)$link['minor_usuario_id'],'parental_consent_recorded','Consentimentos registrados',
            'Seu responsável registrou as permissões da conta. O acesso também seguirá os horários, limites e proteções definidos no painel familiar.',
            ['consent_id'=>$consentId]);
        criarNotificacao($pdo,$guardianUsuarioId,'parental_consent_recorded','Consentimentos salvos',
            'As autorizações de '.(string)$link['minor_nome'].' foram registradas e podem ser revisadas ou revogadas a qualquer momento.',
            ['minor_user_id'=>(int)$link['minor_usuario_id'],'consent_id'=>$consentId]);
        $pdo->commit();
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        throw $e;
    }

    afLogSeguranca($pdo,'parental_consent_saved',10,[
        'link_id'=>$linkId,'minor_user_id'=>(int)$link['minor_usuario_id'],'permissions'=>$normalized
    ],$guardianUsuarioId);
    if(function_exists('afGuardianDashboardEnsureControls')){
        try{afGuardianDashboardEnsureControls($pdo,$guardianUsuarioId,$linkId);}catch(Throwable $e){if(defined('APP_DEBUG')&&APP_DEBUG)error_log('[AURA-GUARDIAN-CONTROLS] '.$e->getMessage());}
    }
    if(function_exists('afMinorPolicyClearCache'))afMinorPolicyClearCache((int)$link['minor_usuario_id']);
    return afConsentCurrentForLink($pdo,$linkId) ?: [];
}

function afConsentRevoke(PDO $pdo, int $guardianUsuarioId, int $linkId, string $reason = 'Revogado pelo responsável'): void
{
    $link = afConsentGetLink($pdo,$guardianUsuarioId,$linkId);
    $current = afConsentCurrentForLink($pdo,$linkId);
    if (!$current) throw new RuntimeException('Não existe consentimento ativo para este dependente.');
    $reason = substr(trim(strip_tags($reason)),0,255) ?: 'Revogado pelo responsável';

    $pdo->beginTransaction();
    try {
        $pdo->prepare("UPDATE af_parental_consents SET status='revoked',revogado_em=NOW(),motivo_revogacao=?,atualizado_em=NOW() WHERE id=?")
            ->execute([$reason,(int)$current['id']]);
        $pdo->prepare('UPDATE af_consent_permissions SET revogado_em=NOW(),atualizado_em=NOW() WHERE consent_id=? AND revogado_em IS NULL')
            ->execute([(int)$current['id']]);
        $pdo->prepare("UPDATE af_guardian_minor_links SET status='verified_pending_consent',atualizado_em=NOW() WHERE id=?")
            ->execute([$linkId]);
        $pdo->prepare("UPDATE af_user_age_profiles SET status_idade='minor_pending_guardian',atualizado_em=NOW() WHERE usuario_id=? AND tipo_conta='minor'")
            ->execute([(int)$link['minor_usuario_id']]);
        $pdo->prepare('UPDATE af_perfis SET perfil_privado=1,atualizado_em=NOW() WHERE usuario_id=?')
            ->execute([(int)$link['minor_usuario_id']]);
        $pdo->prepare("INSERT INTO af_age_status_history
            (usuario_id,status_anterior,status_novo,motivo,actor_usuario_id,dados,criado_em)
            VALUES (?,'minor_authorized','minor_pending_guardian','consentimentos parentais revogados',?,?,NOW())")
            ->execute([(int)$link['minor_usuario_id'],$guardianUsuarioId,json_encode(['consent_id'=>(int)$current['id'],'reason'=>$reason],JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)]);
        afConsentAudit($pdo,$linkId,$guardianUsuarioId,'consent_revoked',['reason'=>$reason],(int)$current['id']);
        criarNotificacao($pdo,(int)$link['minor_usuario_id'],'parental_consent_revoked','Consentimentos revogados',
            'Seu responsável revogou as autorizações. Todos os recursos sensíveis permanecem bloqueados.',
            ['consent_id'=>(int)$current['id']]);
        $pdo->commit();
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        throw $e;
    }
    afLogSeguranca($pdo,'parental_consent_revoked',15,['link_id'=>$linkId,'reason'=>$reason],$guardianUsuarioId);
}

function afConsentRevokeByLink(PDO $pdo, int $linkId, int $actorUsuarioId, string $reason): void
{
    $current = afConsentCurrentForLink($pdo,$linkId);
    if (!$current) return;
    $pdo->prepare("UPDATE af_parental_consents SET status='revoked',revogado_em=NOW(),motivo_revogacao=?,atualizado_em=NOW() WHERE id=?")
        ->execute([substr($reason,0,255),(int)$current['id']]);
    $pdo->prepare('UPDATE af_consent_permissions SET revogado_em=NOW(),atualizado_em=NOW() WHERE consent_id=? AND revogado_em IS NULL')
        ->execute([(int)$current['id']]);
    afConsentAudit($pdo,$linkId,$actorUsuarioId,'consent_revoked_with_link',['reason'=>$reason],(int)$current['id']);
}

function afConsentResumoDoVinculo(PDO $pdo, int $linkId, ?int $guardianUsuarioId = null): array
{
    if ($guardianUsuarioId !== null) {
        $st = $pdo->prepare('SELECT id,status,minor_usuario_id,guardian_usuario_id FROM af_guardian_minor_links WHERE id=? AND guardian_usuario_id=? LIMIT 1');
        $st->execute([$linkId,$guardianUsuarioId]);
    } else {
        $st = $pdo->prepare('SELECT id,status,minor_usuario_id,guardian_usuario_id FROM af_guardian_minor_links WHERE id=? LIMIT 1');
        $st->execute([$linkId]);
    }
    $link = $st->fetch();
    if (!$link) return ['active'=>false,'status'=>'not_found','consent'=>null,'permissions'=>[]];
    $consent = afConsentCurrentForLink($pdo,$linkId);
    return [
        'active'=>(bool)$consent,
        'status'=>$consent?'active':((string)$link['status']==='verified_pending_consent'?'pending':'unavailable'),
        'consent'=>$consent,
        'permissions'=>$consent['permissions'] ?? [],
        'minor_user_id'=>(int)$link['minor_usuario_id'],
        'guardian_user_id'=>(int)$link['guardian_usuario_id'],
    ];
}

function afConsentResumoDoMenor(PDO $pdo, int $minorUsuarioId): array
{
    $st = $pdo->prepare("SELECT id FROM af_guardian_minor_links
        WHERE minor_usuario_id=? AND status IN ('verified_pending_consent','active') ORDER BY id DESC LIMIT 1");
    $st->execute([$minorUsuarioId]);
    $linkId = (int)($st->fetchColumn() ?: 0);
    if (!$linkId) return ['active'=>false,'status'=>'no_verified_link','consent'=>null,'permissions'=>[]];
    return afConsentResumoDoVinculo($pdo,$linkId,null);
}

function afConsentPermissionAllowed(PDO $pdo, int $minorUsuarioId, string $permissionKey): bool
{
    $st = $pdo->prepare("SELECT p.permitido
        FROM af_guardian_minor_links l
        JOIN af_parental_consents c ON c.link_id=l.id AND c.status='active'
        JOIN af_consent_permissions p ON p.consent_id=c.id AND p.permission_key=? AND p.revogado_em IS NULL
        WHERE l.minor_usuario_id=? AND l.status='active'
        ORDER BY c.id DESC LIMIT 1");
    $st->execute([$permissionKey,$minorUsuarioId]);
    return (bool)$st->fetchColumn();
}


function afConsentApiSummary(?array $consent): ?array
{
    if (!$consent) return null;
    $permissions=[];
    foreach (($consent['permissions'] ?? []) as $key=>$row) {
        $permissions[$key]=!empty($row['allowed']);
    }
    return [
        'id'=>(int)($consent['id'] ?? 0),
        'version'=>(string)($consent['version_key'] ?? ''),
        'status'=>(string)($consent['status'] ?? ''),
        'accepted_at'=>$consent['aceito_em'] ?? null,
        'permissions'=>$permissions,
        'high_risk_locked'=>array_keys(afConsentHighRiskDefinitions()),
        'unlocks_minor_features'=>false,
    ];
}
