<?php
declare(strict_types=1);
namespace App\Community;

use App\Support\CoreHooks;
use App\Support\Hooks;

final class SpamRiskService
{
    public function __construct(private readonly int $moderateScore=35,private readonly int $rejectScore=80){}
    /** @param array<string,mixed> $context */
    public function assess(array $context): SpamAssessment
    {
        $score=0;$reasons=[];
        $add=static function(int $points,string $reason)use(&$score,&$reasons):void{$score+=$points;$reasons[]=$reason;};
        $trust=max(0,(int)($context['trust_level']??0));if($trust===0)$add(10,'new_trust_level');elseif($trust>=2)$score=max(0,$score-5);
        $age=max(0,(int)($context['account_age_hours']??0));if($age<24)$add(15,'new_account');elseif($age<72)$add(5,'young_account');
        if(array_key_exists('email_verified',$context)&&!$context['email_verified'])$add(15,'email_unverified');
        $links=array_key_exists('link_count',$context)?max(0,(int)$context['link_count']):$this->countLinks((string)($context['content']??''));if($links>2)$add(min(30,($links-2)*8),'many_links');
        if(!empty($context['repeated_domain']))$add(20,'repeated_domain');
        if(!empty($context['duplicate']))$add(45,'near_duplicate');
        if(!empty($context['user_burst']))$add(25,'user_burst');
        if(!empty($context['ip_burst']))$add(25,'ip_burst');
        if(!empty($context['honeypot']))$add(100,'honeypot');
        $formAge=(int)($context['form_age_ms']??0);if($formAge>0&&$formAge<800)$add(35,'form_too_fast');
        if(!empty($context['invalid_form_signature']))$add(40,'invalid_form_signature');
        if(!empty($context['banned_domain']))$add(80,'banned_domain');
        $score=max(0,$score);
        $disposition=$score>=$this->rejectScore?'reject':($score>=$this->moderateScore?'moderate':'allow');
        // A shared/proxied IP burst cannot by itself become a hard rejection.
        if($disposition==='reject'&&$reasons===['ip_burst'])$disposition='moderate';
        $assessment = new SpamAssessment($score,array_values(array_unique($reasons)),$disposition);
        $filtered = Hooks::filter(CoreHooks::SPAM_ASSESSMENT, $assessment, $context);
        return $filtered instanceof SpamAssessment ? $filtered : $assessment;
    }
    private function countLinks(string $content):int{preg_match_all('~(?:https?://|www\.)[^\s<]+~iu',$content,$m);return count($m[0]??[]);}
}
