<?php

declare(strict_types=1);

namespace App\Services\Recommendations;

final class RecommendationFeedResolver
{
    public function __construct(
        private readonly PersonalizedFeedService $personalizedFeed,
        private readonly \App\Services\Recommendations\RecommendationServiceV2 $v2Feed,
    ) {
    }

    public function getFeed(int $userId, int $limit = 24, ?string $cursor = null, ?string $algoVersion = null): array
    {
        if ($this->shouldUseV2($userId, $algoVersion)) {
            return $this->v2Feed->getFeed($userId, $limit, $cursor, $algoVersion);
        }

        return $this->personalizedFeed->getFeed($userId, $limit, $cursor, $algoVersion);
    }

    public function regenerateCacheForUser(int $userId, ?string $algoVersion = null): void
    {
        if ($this->shouldUseV2($userId, $algoVersion)) {
            $this->v2Feed->regenerateCacheForUser($userId, $algoVersion);
            return;
        }

        $this->personalizedFeed->regenerateCacheForUser($userId, $algoVersion);
    }

    /**
     * @return array<string, mixed>
     */
    public function inspectDecision(int $userId, ?string $algoVersion = null): array
    {
        $requested = trim((string) ($algoVersion ?? ''));
        $v2AlgoVersion = trim((string) config('discovery.v2.algo_version', 'clip-cosine-v2-adaptive'));
        $v2Enabled = (bool) config('discovery.v2.enabled', false);
        $rollout = max(0, min(100, (int) config('discovery.v2.rollout_percentage', 0)));
        $bucket = abs((int) crc32((string) $userId)) % 100;
        $forcedByAlgoVersion = $requested !== '' && $requested === $v2AlgoVersion;
        $usesV2 = $forcedByAlgoVersion
            || ($v2Enabled && ($rollout >= 100 || ($rollout > 0 && $bucket < $rollout)));

        $reason = match (true) {
            $forcedByAlgoVersion => 'explicit_algo_override',
            ! $v2Enabled => 'v2_disabled',
            $rollout >= 100 => 'full_rollout',
            $rollout <= 0 => 'rollout_zero',
            $bucket < $rollout => 'bucket_in_rollout',
            default => 'bucket_outside_rollout',
        };

        return [
            'user_id' => $userId,
            'requested_algo_version' => $requested !== '' ? $requested : null,
            'v2_algo_version' => $v2AlgoVersion,
            'v2_enabled' => $v2Enabled,
            'rollout_percentage' => $rollout,
            'bucket' => $bucket,
            'bucket_in_rollout' => $bucket < $rollout,
            'forced_by_algo_version' => $forcedByAlgoVersion,
            'uses_v2' => $usesV2,
            'selected_engine' => $usesV2 ? 'v2' : 'v1',
            'reason' => $reason,
        ];
    }

    private function shouldUseV2(int $userId, ?string $algoVersion = null): bool
    {
        return (bool) ($this->inspectDecision($userId, $algoVersion)['uses_v2'] ?? false);
    }
}
