<?php

namespace App\Services;

use App\Facades\License;
use App\Http\Integrations\Ticketmaster\Requests\AttractionSearchRequest;
use App\Http\Integrations\Ticketmaster\Requests\EventSearchRequest;
use App\Http\Integrations\Ticketmaster\TicketmasterConnector;
use App\Services\Geolocation\Contracts\GeolocationService;
use App\Values\Ticketmaster\TicketmasterAttraction;
use App\Values\Ticketmaster\TicketmasterEvent;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

class TicketmasterService
{
    public function __construct(
        private readonly TicketmasterConnector $connector,
        private readonly GeolocationService $geolocator,
        private readonly string $defaultCountryCode,
    ) {
    }

    public static function used(): bool
    {
        return License::isPlus() && config('koel.services.ticketmaster.key');
    }

    /** @return Collection<TicketmasterEvent>|array<array-key, TicketmasterEvent> */
    public function searchEventForArtist(string $artistName, string $ip): Collection
    {
        $countryCode = $this->geolocator->getCountryCodeFromIp($ip) ?: $this->defaultCountryCode;

        return rescue(function () use ($artistName, $countryCode) {
            return Cache::remember(
                cache_key('Ticketmaster events', $artistName, $countryCode),
                now()->addDay(),
                function () use ($artistName, $countryCode): Collection {
                    $attractionId = $this->getAttractionIdForArtist($artistName);

                    return $attractionId
                        ? $this->connector->send(new EventSearchRequest($attractionId, $countryCode))->dto()
                        : collect();
                }
            );
        }, collect());
    }

    private function getAttractionIdForArtist(string $artistName): ?string
    {
        return rescue(function () use ($artistName): ?string {
            return Cache::remember(
                cache_key('Ticketmaster attraction id', $artistName),
                now()->addMonth(),
                function () use ($artistName): ?string {
                    /** @var Collection<TicketmasterAttraction>|array<array-key, TicketmasterAttraction> $attractions */
                    $attractions = $this->connector->send(new AttractionSearchRequest($artistName))->dto();

                    return $attractions->firstWhere(
                        static function (TicketmasterAttraction $attraction) use ($artistName) {
                            return Str::lower($attraction->name) === Str::lower($artistName);
                        }
                    )?->id;
                }
            );
        });
    }
}