<?php

declare(strict_types=1);

namespace ImovelZapAi\Publishing\Application\Actions;

use ImovelZapAi\Publishing\Application\Queries\PublishedFeedPropertiesQuery;
use ImovelZapAi\Publishing\Application\Services\TenantFeedBuilder;
use ImovelZapAi\Publishing\Application\Services\TenantFeedGenerationLogger;
use ImovelZapAi\Publishing\Application\Services\TenantFeedMetadataRecorder;
use ImovelZapAi\Publishing\Application\Services\TenantFeedStorage;
use ImovelZapAi\Publishing\Domain\Exceptions\InvalidListingDataFeedXmlException;
use Illuminate\Support\Facades\Log;

/**
 * Reconstrói o cache do feed agregado — executado apenas pelo worker.
 */
final class RebuildTenantFeedAction
{
    public function __construct(
        private readonly TenantFeedBuilder $builder,
        private readonly TenantFeedStorage $storage,
        private readonly PublishedFeedPropertiesQuery $publishedProperties,
        private readonly TenantFeedMetadataRecorder $metadataRecorder,
        private readonly TenantFeedGenerationLogger $generationLogger,
    ) {}

    public function execute(string $tenantId): bool
    {
        $startedAt = microtime(true);
        $listingCount = count($this->publishedProperties->execute($tenantId));

        try {
            $xml = $this->builder->buildForTenant($tenantId);
        } catch (InvalidListingDataFeedXmlException $exception) {
            $errors = $exception->validation->errors;
            $message = $exception->validation->firstError() ?? 'XML VRSync inválido.';

            Log::warning('Tenant feed rebuild failed validation.', [
                'tenant_id' => $tenantId,
                'error' => $message,
            ]);

            $this->metadataRecorder->recordGeneration($tenantId, $listingCount, $message);
            $this->logGeneration($tenantId, $listingCount, $startedAt, false, null, $errors);

            return false;
        }

        if ($xml === null) {
            $this->storage->delete($tenantId);
            $this->metadataRecorder->recordGeneration($tenantId, 0);
            $this->logGeneration($tenantId, 0, $startedAt, true, null);

            return true;
        }

        $this->storage->store($tenantId, $xml);
        $this->metadataRecorder->recordGeneration($tenantId, $listingCount);
        $this->logGeneration($tenantId, $listingCount, $startedAt, true, hash('sha256', $xml));

        return true;
    }

    /**
     * @param  list<string>  $errors
     */
    private function logGeneration(
        string $tenantId,
        int $listingCount,
        float $startedAt,
        bool $success,
        ?string $contentHash,
        array $errors = [],
    ): void {
        $durationMs = (int) round((microtime(true) - $startedAt) * 1000);

        $this->generationLogger->record(
            tenantId: $tenantId,
            listingCount: $listingCount,
            durationMs: $durationMs,
            success: $success,
            contentHash: $contentHash,
            errors: $errors,
        );
    }
}
