<?php

namespace App\Http\Livewire\Calls;

use App\Models\Call;

class CallCarouselScorer
{
    private array $cfg;
    private ?int  $profileCityId;
    private ?int  $profileDivisionId;
    private ?int  $profileCountryId;

    private const UNKNOWN_COUNTRY_ID = 10;
    private const REACTION_TYPE_LIKE = 3;
    private const REACTION_TYPE_STAR = 1;

    public function __construct(
        array $carouselConfig,
        ?int  $profileCityId,
        ?int  $profileDivisionId,
        ?int  $profileCountryId
    ) {
        $this->cfg               = $carouselConfig;
        $this->profileCityId     = $profileCityId;
        $this->profileDivisionId = $profileDivisionId;
        $this->profileCountryId  = $profileCountryId;
    }

    public function score(Call $call): float
    {
        $score = 1.0;
        $loc   = $call->location;

        // --- Location specificity (only best-matching tier applied) ---
        if ($loc) {
            if ($loc->country_id === self::UNKNOWN_COUNTRY_ID) {
                $score *= (float) ($this->cfg['boost_location_unknown'] ?? 0.8);
            } elseif ($loc->city_id) {
                $score *= (float) ($this->cfg['boost_location_city'] ?? 2.0);
            } elseif ($loc->division_id) {
                $score *= (float) ($this->cfg['boost_location_division'] ?? 1.5);
            } elseif ($loc->country_id) {
                $score *= (float) ($this->cfg['boost_location_country'] ?? 1.1);
            }

            // Same-city (district) proximity bonus
            if ($this->profileCityId && $loc->city_id === $this->profileCityId) {
                $score *= (float) ($this->cfg['boost_same_district'] ?? 3.0);
            }
        }

        // --- Engagement: likes on the call ---
        $likeCount  = $call->loveReactant?->reactionCounters
            ->firstWhere('reaction_type_id', self::REACTION_TYPE_LIKE)?->count ?? 0;
        $score     *= (1.0 + $likeCount * (float) ($this->cfg['boost_like_count'] ?? 0.05));

        // --- Engagement: stars on the callable ---
        $starCount  = $call->callable?->loveReactant?->reactionCounters
            ->firstWhere('reaction_type_id', self::REACTION_TYPE_STAR)?->count ?? 0;
        $score     *= (1.0 + $starCount * (float) ($this->cfg['boost_star_count'] ?? 0.10));

        // --- Recency (created_at) ---
        $recentDays = (int) ($this->cfg['recent_days'] ?? 14);
        if ($call->created_at && $call->created_at->gte(now()->subDays($recentDays))) {
            $score *= (float) ($this->cfg['boost_recent_from'] ?? 1.3);
        }

        // --- Urgency (till expiry) ---
        $soonDays = (int) ($this->cfg['soon_days'] ?? 7);
        if ($call->till && $call->till->lte(now()->addDays($soonDays))) {
            $score *= (float) ($this->cfg['boost_soon_till'] ?? 1.2);
        }

        // --- Callable type ---
        $callableType = $call->callable_type ?? '';
        if (str_ends_with($callableType, 'User')) {
            $score *= (float) ($this->cfg['boost_callable_user'] ?? 1.0);
        } elseif (str_ends_with($callableType, 'Organization')) {
            $score *= (float) ($this->cfg['boost_callable_organization'] ?? 1.2);
        } elseif (str_ends_with($callableType, 'Bank')) {
            $score *= (float) ($this->cfg['boost_callable_bank'] ?? 1.0);
        }

        return $score;
    }
}
