<?php

namespace App\Services\ProductOwner;

use App\Contracts\ProductOwnerClientContract;
use App\DTOs\ProductOwner\ActivationRequestData;
use App\Support\EnvWriter;
use App\Support\ProductOwnerUnavailable;

class InstallationSyncService
{
    private bool $platformUnavailable = false;

    public function __construct(
        private readonly ProductOwnerClientContract $productOwnerClient,
        private readonly EnvWriter $envWriter,
    ) {}

    public function isPlatformUnavailable(): bool
    {
        return $this->platformUnavailable;
    }

    public function ensureRegistered(): bool
    {
        $this->platformUnavailable = false;

        if (config('product_owner.driver') === 'mock') {
            return true;
        }

        $installationId = (string) config('product_owner.installation_id');
        $licenseKey = (string) config('product_owner.license_key');

        if ($installationId === '' || $licenseKey === '') {
            return false;
        }

        $validation = $this->productOwnerClient->validateLicense($licenseKey, $installationId);

        if ($validation->valid) {
            return true;
        }

        if ($this->isPlatformUnavailableResponse($validation->status, $validation->message)) {
            $this->platformUnavailable = true;

            return false;
        }

        if (! $this->isMissingInstallation($validation->message)) {
            return false;
        }

        return $this->reactivate($installationId, $licenseKey);
    }

    private function isPlatformUnavailableResponse(?string $status, ?string $message): bool
    {
        return $status === 'unavailable' || ProductOwnerUnavailable::isUnavailableMessage($message);
    }

    private function isMissingInstallation(?string $message): bool
    {
        return str_contains(strtolower($message ?? ''), 'installation not found');
    }

    private function reactivate(string $installationId, string $licenseKey): bool
    {
        $response = $this->productOwnerClient->activate(new ActivationRequestData(
            licenseKey: $licenseKey,
            productName: config('installer.product_name', config('app.name')),
            productVersion: config('installer.version', '1.0.0'),
            domain: parse_url((string) config('app.url'), PHP_URL_HOST) ?: 'localhost',
            installationId: $installationId,
        ));

        if ($response->success) {
            $resolvedInstallationId = $response->installationId ?? $installationId;

            $this->envWriter->setMany([
                'INSTALLATION_ID' => $resolvedInstallationId,
                'ACTIVATION_TOKEN' => $response->activationToken,
                'API_SECRET' => $response->apiSecret,
            ]);

            $this->refreshRuntimeConfig([
                'INSTALLATION_ID' => $resolvedInstallationId,
                'ACTIVATION_TOKEN' => $response->activationToken,
                'API_SECRET' => $response->apiSecret,
            ]);

            return true;
        }

        if (ProductOwnerUnavailable::isUnavailableMessage($response->message)) {
            $this->platformUnavailable = true;
        }

        return false;
    }

    /**
     * @param  array<string, string|null>  $variables
     */
    private function refreshRuntimeConfig(array $variables): void
    {
        $map = [
            'INSTALLATION_ID' => 'product_owner.installation_id',
            'ACTIVATION_TOKEN' => 'product_owner.activation_token',
            'API_SECRET' => 'product_owner.api_secret',
            'LICENSE_KEY' => 'product_owner.license_key',
        ];

        foreach ($map as $envKey => $configKey) {
            if (! array_key_exists($envKey, $variables)) {
                continue;
            }

            $value = $variables[$envKey];
            config([$configKey => $value]);
            putenv("{$envKey}={$value}");
            $_ENV[$envKey] = $value;
            $_SERVER[$envKey] = $value;
        }
    }
}
