<?php

namespace App\Domain\System\Infrastructure\ApiPlatform\State\Provider;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Domain\System\Application\Query\GetSystemStatusQuery;
use App\Domain\System\Application\QueryHandler\GetSystemStatusQueryHandler;
use App\Domain\System\Domain\Model\SystemStatus;
use App\Domain\System\Infrastructure\ApiPlatform\Resource\GetSystemStatusResource;

final class GetSystemStatusStateProvider implements ProviderInterface
{
    public function __construct(
        private readonly GetSystemStatusQueryHandler $handler,
    ) {
    }

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): GetSystemStatusResource
    {
        $response = $this->handler->handle(new GetSystemStatusQuery());

        return $this->toResource($response);
    }

    private function toResource(SystemStatus $response): GetSystemStatusResource
    {
        $resource = new GetSystemStatusResource();
        $resource->id = 'current';

        $resource->totalMangas = $response->totalMangas;
        $resource->monitoredMangas = $response->monitoredMangas;
        $resource->mangasByStatus = $response->mangasByStatus;

        $resource->totalChapters = $response->totalChapters;
        $resource->downloadedChapters = $response->downloadedChapters;
        $resource->pendingChapters = $response->totalChapters - $response->downloadedChapters;

        $resource->totalJobs = $response->totalJobs;
        $resource->completedJobs = $response->completedJobs;
        $resource->failedJobs = $response->failedJobs;
        $resource->pendingJobs = $response->pendingJobs;
        $resource->inProgressJobs = $response->inProgressJobs;

        $resource->totalJobsLast24h = $response->totalJobsLast24h;
        $resource->completedJobsLast24h = $response->completedJobsLast24h;
        $resource->failedJobsLast24h = $response->failedJobsLast24h;
        $resource->successRateLast24h = $response->totalJobsLast24h > 0
            ? round($response->completedJobsLast24h / $response->totalJobsLast24h * 100, 1)
            : 0.0;

        $resource->totalJobsLast7d = $response->totalJobsLast7d;
        $resource->completedJobsLast7d = $response->completedJobsLast7d;
        $resource->failedJobsLast7d = $response->failedJobsLast7d;
        $resource->successRateLast7d = $response->totalJobsLast7d > 0
            ? round($response->completedJobsLast7d / $response->totalJobsLast7d * 100, 1)
            : 0.0;

        $resource->storagePath = $response->storagePath;
        $resource->storageTotalBytes = $response->storageTotalBytes;
        $resource->storageFreeBytes = $response->storageFreeBytes;
        $resource->storageUsedBytes = $response->storageUsedBytes;
        $resource->storageTotalHuman = $this->formatBytes($response->storageTotalBytes);
        $resource->storageFreeHuman = $this->formatBytes($response->storageFreeBytes);
        $resource->storageUsedHuman = $this->formatBytes($response->storageUsedBytes);

        $resource->totalSources = $response->totalSources;
        $resource->sourcesByHealth = $response->sourcesByHealth;

        $resource->phpVersion = $response->phpVersion;
        $resource->generatedAt = $response->generatedAt->format(\DateTimeInterface::ATOM);

        return $resource;
    }

    private function formatBytes(int $bytes): string
    {
        if ($bytes <= 0) {
            return '0 B';
        }

        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $exp = (int) floor(log($bytes, 1024));
        $exp = min($exp, count($units) - 1);

        return round($bytes / (1024 ** $exp), 2).' '.$units[$exp];
    }
}
