<?php

namespace App\Http\Controllers;

use App\Models\Ride;
use App\Models\RideRecommendation;
use App\Services\EventTracker;
use App\Services\RecommendationEngine;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class RideController extends Controller
{
    public function __construct(
        protected RecommendationEngine $recommendationEngine,
        protected EventTracker $eventTracker,
    ) {
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'pickup_label' => ['required', 'string', 'max:255'],
            'destination_label' => ['required', 'string', 'max:255'],
            'scheduled_for' => ['nullable', 'date'],
            'source_channel' => ['required', 'in:app,hotel,reception,web'],
            'locale' => ['nullable', 'string', 'max:10'],
        ]);

        $ride = Ride::create([
            'pickup_label' => $validated['pickup_label'],
            'destination_label' => $validated['destination_label'],
            'scheduled_for' => $validated['scheduled_for'] ?? null,
            'status' => 'confirmed',
            'eta_minutes' => $this->estimateEta($validated['pickup_label'], $validated['destination_label']),
            'source_channel' => $validated['source_channel'],
            'context_zone' => $this->resolveZone($validated['destination_label']),
            'locale' => $validated['locale'] ?? app()->getLocale(),
        ]);

        $this->eventTracker->log('request_created', $ride, meta: [
            'source_channel' => $ride->source_channel,
            'context_zone' => $ride->context_zone,
        ]);

        $this->syncRecommendations($ride);

        return redirect()->route('rides.confirmed', $ride);
    }

    public function confirmed(Ride $ride): View
    {
        $ride->load(['recommendations.offer']);

        if ($ride->recommendations->isEmpty()) {
            $this->syncRecommendations($ride);
            $ride->load(['recommendations.offer']);
        }

        foreach ($ride->recommendations as $recommendation) {
            $this->eventTracker->logOncePerSession(
                'recommendation_viewed',
                'rec-viewed-'.$recommendation->id,
                $ride,
                $recommendation->offer,
                null,
                $recommendation,
                ['position' => $recommendation->position]
            );

            if (!$recommendation->was_viewed) {
                $recommendation->forceFill(['was_viewed' => true])->save();
            }
        }

        return view('rides.confirmed', [
            'ride' => $ride,
            'recommendations' => $ride->recommendations,
        ]);
    }

    protected function syncRecommendations(Ride $ride): void
    {
        $offers = $this->recommendationEngine->recommendFor($ride, 3);

        $ride->recommendations()->delete();

        foreach ($offers as $index => $offer) {
            RideRecommendation::create([
                'ride_id' => $ride->id,
                'offer_id' => $offer->id,
                'position' => $index + 1,
                'score' => $offer->demo_score,
                'reason' => $offer->demo_reason,
                'was_viewed' => false,
                'was_clicked' => false,
            ]);
        }
    }

    protected function resolveZone(string $destinationLabel): string
    {
        $normalized = mb_strtolower($destinationLabel);

        return match (true) {
            str_contains($normalized, 'beach') => 'beach',
            str_contains($normalized, 'old town') => 'old town',
            str_contains($normalized, 'marina') => 'marina',
            str_contains($normalized, 'center'), str_contains($normalized, 'centre') => 'city center',
            default => trim($destinationLabel),
        };
    }

    protected function estimateEta(string $pickup, string $destination): int
    {
        $seed = strlen($pickup) + strlen($destination);
        return max(4, min(16, ($seed % 13) + 4));
    }
}
