<?php

namespace App\Services\Achievements\Checkers;

use App\Models\Achievement;
use App\Services\Achievements\AchievementService;
use Illuminate\Support\Collection;

abstract class BaseChecker implements AchievementCheckerInterface
{
    public function __construct(protected AchievementService $service) {}

    protected function flights(): Collection
    {
        return $this->service->getFlights();
    }

    /**
     * Resolve an achievement ID from its internal name.
     * Results are cached on the service so repeated lookups are free.
     */
    protected function achievement(string $internalName): ?Achievement
    {
        return $this->service->resolveAchievement($internalName);
    }

    /**
     * Award a boolean (non-progressive) achievement if the condition is met,
     * or revoke it if the condition is no longer met.
     */
    protected function awardIf(bool $condition, string $internalName): void
    {
        $achievement = $this->achievement($internalName);

        if (! $achievement) {
            return;
        }

        if ($condition) {
            $this->service->award($achievement, $this->currentUser());
        } else {
            $this->service->revoke($achievement, $this->currentUser());
        }
    }

    /**
     * Award a progressive achievement, updating progress and
     * unlocking/revoking based on whether progress meets the threshold.
     */
    protected function awardProgress(int $progress, string $internalName): void
    {
        $achievement = $this->achievement($internalName);
        if (! $achievement) return;

        if ($progress >= $achievement->threshold) {
            $this->service->award($achievement, $this->currentUser(), $progress);
        } else {
            $this->service->updateProgress($achievement, $this->currentUser(), $progress);
        }
    }

    /**
     * The user currently being evaluated.
     * Set by AchievementService before calling check().
     */
    protected function currentUser(): \App\Models\User
    {
        return $this->service->currentUser();
    }
}
