<?php

declare(strict_types=1);

namespace ImovelZapAi\Publishing\Application\Queries;

use Carbon\Carbon;
use ImovelZapAi\Publishing\Application\Data\PublishingDashboardMetricsData;
use ImovelZapAi\Publishing\Domain\Enums\PublicationTargetStatus;
use ImovelZapAi\Publishing\Infrastructure\Persistence\Eloquent\PublicationModel;
use ImovelZapAi\Publishing\Infrastructure\Persistence\Eloquent\PublicationTargetModel;

final class GetPublishingDashboardMetricsQuery
{
    public function execute(): PublishingDashboardMetricsData
    {
        $publications = PublicationModel::query()
            ->with('targets')
            ->get();

        $published = 0;
        $pending = 0;
        $error = 0;

        foreach ($publications as $publication) {
            $bucket = $this->classifyProperty($publication->targets->pluck('status')->all());

            match ($bucket) {
                'published' => $published++,
                'pending' => $pending++,
                'error' => $error++,
                default => null,
            };
        }

        $lastSyncedRaw = PublicationTargetModel::query()->max('last_synced_at');

        return new PublishingDashboardMetricsData(
            publishedProperties: $published,
            pendingProperties: $pending,
            errorProperties: $error,
            lastSyncedAt: is_string($lastSyncedRaw) || $lastSyncedRaw instanceof \DateTimeInterface
                ? Carbon::parse($lastSyncedRaw)
                : null,
        );
    }

    /**
     * @param  list<PublicationTargetStatus>  $statuses
     */
    private function classifyProperty(array $statuses): ?string
    {
        $active = array_values(array_filter(
            $statuses,
            static fn (PublicationTargetStatus $status): bool => $status !== PublicationTargetStatus::Removed,
        ));

        if ($active === []) {
            return null;
        }

        foreach ($active as $status) {
            if ($status === PublicationTargetStatus::Failed) {
                return 'error';
            }
        }

        foreach ($active as $status) {
            if (in_array($status, [PublicationTargetStatus::Pending, PublicationTargetStatus::Publishing], true)) {
                return 'pending';
            }
        }

        foreach ($active as $status) {
            if ($status === PublicationTargetStatus::Published) {
                return 'published';
            }
        }

        return null;
    }
}
