<?php

namespace App\Services;

use App\Models\Offer;
use App\Models\Ride;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class RecommendationEngine
{
    public function recommendFor(Ride $ride, int $limit = 3): Collection
    {
        $zone = Str::lower((string) $ride->context_zone);
        $destination = Str::lower((string) $ride->destination_label);
        $hour = optional($ride->scheduled_for)->hour ?? now()->hour;

        return Offer::query()
            ->where('status', 'published')
            ->get()
            ->map(function (Offer $offer) use ($zone, $destination, $hour) {
                $score = (int) $offer->priority_score;
                $reasons = [];
                $haystack = Str::lower(trim(($offer->location_label ?? '').' '.$offer->title.' '.$offer->excerpt.' '.$offer->description));

                if ($offer->available_now) {
                    $score += 18;
                    $reasons[] = 'Available right now';
                }

                if ($offer->is_featured) {
                    $score += 14;
                    $reasons[] = 'Featured partner';
                }

                foreach (array_filter([$zone, $destination]) as $needle) {
                    if ($needle !== '' && Str::contains($haystack, $needle)) {
                        $score += 22;
                        $reasons[] = 'Matches destination context';
                        break;
                    }
                }

                if ($hour >= 18 && $offer->category === 'restaurant') {
                    $score += 12;
                    $reasons[] = 'Good fit for the evening';
                }

                if ($hour >= 10 && $hour <= 18 && in_array($offer->category, ['experience', 'activity'], true)) {
                    $score += 12;
                    $reasons[] = 'Works well while waiting or after arrival';
                }

                if (($offer->duration_minutes ?? 0) > 0 && $offer->duration_minutes <= 120) {
                    $score += 8;
                    $reasons[] = 'Easy to fit into today';
                }

                if (($offer->price_from ?? 0) > 0 && $offer->price_from <= 50) {
                    $score += 6;
                    $reasons[] = 'Easy price point';
                }

                $offer->demo_score = $score;
                $offer->demo_reason = collect($reasons)->unique()->take(2)->implode(' · ') ?: 'Strong local fit';
                return $offer;
            })
            ->sortByDesc(fn (Offer $offer) => [$offer->demo_score, $offer->is_featured, $offer->priority_score])
            ->take($limit)
            ->values();
    }
}
