<?php

namespace App\Modules\Integrations\Platform\Services;

use App\Modules\Integrations\Platform\Models\IntegrationWebhook;
use App\Modules\Integrations\Platform\Repositories\IntegrationWebhookRepository;
use Illuminate\Support\Facades\Crypt;

final class WebhookManagementService
{
    public function __construct(
        private readonly IntegrationWebhookRepository $webhooks,
        private readonly WebhookTestDeliveryService $testDelivery,
    ) {}

    /**
     * @param  list<string>  $topics
     * @return array{webhook: IntegrationWebhook, plain_secret: string}
     */
    public function create(int $tenantId, string $name, string $url, array $topics): array
    {
        $plain = bin2hex(random_bytes(32));
        $webhook = IntegrationWebhook::query()->create([
            'tenant_id' => $tenantId,
            'name' => $name,
            'url' => $url,
            'secret_enc' => Crypt::encryptString($plain),
            'topics' => array_values(array_unique($topics)),
            'is_active' => true,
            'health_status' => 'healthy',
            'failure_count' => 0,
        ]);

        return ['webhook' => $webhook, 'plain_secret' => $plain];
    }

    /**
     * @param  list<string>|null  $topics
     */
    public function update(IntegrationWebhook $webhook, ?string $name, ?string $url, ?array $topics): IntegrationWebhook
    {
        $data = [];
        if ($name !== null) {
            $data['name'] = $name;
        }
        if ($url !== null) {
            $data['url'] = $url;
        }
        if ($topics !== null) {
            $data['topics'] = array_values(array_unique($topics));
        }
        if ($data !== []) {
            $webhook->fill($data)->save();
        }

        return $webhook->refresh();
    }

    public function delete(IntegrationWebhook $webhook): void
    {
        $this->webhooks->delete($webhook);
    }

    /**
     * @return array{webhook: IntegrationWebhook, plain_secret: string}
     */
    public function rotateSecret(IntegrationWebhook $webhook): array
    {
        $plain = bin2hex(random_bytes(32));
        $webhook->forceFill(['secret_enc' => Crypt::encryptString($plain)])->save();

        return ['webhook' => $webhook->refresh(), 'plain_secret' => $plain];
    }

    public function setEnabled(IntegrationWebhook $webhook, bool $enabled): IntegrationWebhook
    {
        $webhook->forceFill(['is_active' => $enabled])->save();

        return $webhook->refresh();
    }

    /**
     * @return array{ok:bool, http_status:?int, error:?string, request_id:string}
     */
    public function test(IntegrationWebhook $webhook): array
    {
        return $this->testDelivery->sendTest($webhook);
    }

    public function findForTenant(int $tenantId, int $id): ?IntegrationWebhook
    {
        return $this->webhooks->findForTenant($tenantId, $id);
    }
}
