<?php

/**
 * =============================================================================
 * MODPACK VERSION CHECKER - CRON COMMAND
 * =============================================================================
 * 
 * Laravel Artisan command that checks all servers for modpack updates.
 * This is the "brain" that populates the cache used by the dashboard badges.
 * 
 * USAGE:
 *     php artisan modpackchecker:check
 * 
 * RECOMMENDED CRON SCHEDULE:
 *     # Check for updates every 6 hours (adjust based on your server count)
 *     0 */6 * * * cd /var/www/pterodactyl && php artisan modpackchecker:check >> /dev/null 2>&1
 * 
 * HOW IT WORKS:
 * 1. Finds all servers with MODPACK_PLATFORM egg variable set
 * 2. Loops through each server, checking via ModpackApiService
 * 3. Stores results in modpackchecker_servers database table
 * 4. Dashboard badges read from this table (never calling APIs directly)
 * 
 * RATE LIMITING:
 * Each API call is followed by a 2-second sleep to avoid rate limits.
 * For 50 servers, a full check takes ~2 minutes.
 * 
 * @package     Pterodactyl\Console\Commands
 * @author      Firefrost Gaming / Frostystyle <dev@firefrostgaming.com>
 * @version     1.0.0
 * @see         ModpackApiService.php (centralized API logic)
 * @see         ModpackAPIController.php (provides getStatus endpoint for badges)
 * =============================================================================
 */

namespace Pterodactyl\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Pterodactyl\Models\Server;
use Pterodactyl\Services\ModpackApiService;

class CheckModpackUpdates extends Command
{
    protected $signature = 'modpackchecker:check';
    protected $description = 'Check all servers for modpack updates';
    
    public function __construct(private ModpackApiService $apiService)
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     * 
     * @return int  Exit code (0 = success)
     */
    public function handle(): int
    {
        $this->info('Starting modpack update check...');

        // Get all servers that have modpack variables set
        $servers = Server::whereHas('variables', function ($q) {
            $q->where('env_variable', 'MODPACK_PLATFORM');
        })->get();

        $this->info("Found {$servers->count()} servers with modpack configuration");

        foreach ($servers as $server) {
            $this->checkServer($server);
            // Rate limiting - sleep between checks
            sleep(2);
        }

        $this->info('Modpack update check complete!');
        return 0;
    }

    /**
     * Check a single server for modpack updates.
     * 
     * @param  Server  $server  The server to check
     * @return void
     */
    private function checkServer(Server $server): void
    {
        $this->line("Checking: {$server->name} ({$server->uuid})");

        try {
            $platform = $this->getVariable($server, 'MODPACK_PLATFORM');
            $modpackId = $this->getVariable($server, 'MODPACK_ID');

            if (!$platform || !$modpackId) {
                $this->warn("  Skipping - missing platform or modpack ID");
                return;
            }

            // Centralized API Call via Service
            $latestData = $this->apiService->fetchLatestVersion($platform, $modpackId);
            $currentVersion = $this->getVariable($server, 'MODPACK_CURRENT_VERSION');
            $updateAvailable = $currentVersion && $currentVersion !== $latestData['version'];

            $this->updateDatabase($server, [
                'platform' => $platform,
                'modpack_id' => $modpackId,
                'modpack_name' => $latestData['name'],
                'current_version' => $currentVersion,
                'latest_version' => $latestData['version'],
                'status' => $updateAvailable ? 'update_available' : 'up_to_date',
                'error_message' => null,
                'last_checked' => now(),
            ]);

            $statusIcon = $updateAvailable ? '🟠 UPDATE AVAILABLE' : '🟢 Up to date';
            $this->info("  {$statusIcon}: {$latestData['name']} - {$latestData['version']}");

        } catch (\Exception $e) {
            $this->error("  Error: {$e->getMessage()}");
            $this->updateDatabase($server, [
                'status' => 'error',
                'error_message' => $e->getMessage(),
                'last_checked' => now(),
            ]);
        }
    }

    /**
     * Get an egg variable value from a server.
     * 
     * @param  Server  $server  The server to query
     * @param  string  $name    The variable name
     * @return string|null      The variable value, or null if not set
     */
    private function getVariable(Server $server, string $name): ?string
    {
        $variable = $server->variables()
            ->where('env_variable', $name)
            ->first();
        return $variable?->server_value;
    }

    /**
     * Store or update the modpack check results in the database.
     * 
     * Uses updateOrInsert for upsert behavior.
     * The server_uuid column is the unique key for matching.
     * 
     * @param  Server  $server  The server being checked
     * @param  array   $data    The data to store
     * @return void
     */
    private function updateDatabase(Server $server, array $data): void
    {
        DB::table('modpackchecker_servers')->updateOrInsert(
            ['server_uuid' => $server->uuid],
            array_merge($data, ['updated_at' => now()])
        );
    }
}
