<?php
namespace App\Services;
use App\Enums\SerpCheckStatus;use App\Models\{Keyword,SerpCheck};use Illuminate\Support\Collection;
final class RankingHistoryService{
 public function checksFor(Collection $keywordIds,\DateTimeInterface $from,\DateTimeInterface $to):Collection{return SerpCheck::query()->whereIn('keyword_id',$keywordIds)->where('status',SerpCheckStatus::Completed)->whereBetween('checked_at',[$from,$to])->with(['keyword.project','results'=>fn($q)=>$q->where('result_type','organic')->where('is_project_domain',true)->orderBy('position')])->orderBy('checked_at')->get()->unique(fn($c)=>$c->keyword_id.'|'.$c->checked_at?->format('Y-m-d H:i:s'))->values();}
 public function rank(SerpCheck $check):?int{return $check->results->min('position');}
 public function rows(Collection $checks):Collection{return $checks->groupBy('keyword_id')->flatMap(function(Collection $items){$previous=null;return $items->sortBy('checked_at')->map(function($check)use(&$previous){$rank=$this->rank($check);$row=['check'=>$check,'keyword'=>$check->keyword,'project'=>$check->keyword->project,'rank'=>$rank,'previous'=>$previous,'change'=>$rank!==null&&$previous!==null?$previous-$rank:null,'movement'=>$rank===null?'unranked':($previous===null?'new':($rank<$previous?'winner':($rank>$previous?'loser':'unchanged')))];if($rank!==null)$previous=$rank;return $row;});})->sortByDesc(fn($r)=>$r['check']->checked_at)->values();}
 public function latest(Collection $rows):Collection{return $rows->groupBy(fn($r)=>$r['keyword']->id)->map(fn($items)=>$items->sortByDesc(fn($r)=>$r['check']->checked_at)->first())->values();}
 public function summary(Collection $rows,int $tracked):array{$latest=$this->latest($rows);$ranked=$latest->whereNotNull('rank');return ['tracked'=>$tracked,'average'=>$ranked->isEmpty()?null:round($ranked->avg('rank'),1),'top3'=>$ranked->where('rank','<=',3)->count(),'top10'=>$ranked->where('rank','<=',10)->count(),'winners'=>$latest->where('movement','winner')->count(),'losers'=>$latest->where('movement','loser')->count()];}
 public function distribution(Collection $rows):array{$latest=$this->latest($rows);return ['top3'=>$latest->whereBetween('rank',[1,3])->count(),'4_10'=>$latest->whereBetween('rank',[4,10])->count(),'11_20'=>$latest->whereBetween('rank',[11,20])->count(),'21_50'=>$latest->whereBetween('rank',[21,50])->count(),'51_100'=>$latest->whereBetween('rank',[51,100])->count(),'unranked'=>$latest->whereNull('rank')->count()];}
}
