<?php

namespace App\Libraries;

use Config\Deployment;

class SignatureService
{
    protected Deployment $config;

    public function __construct()
    {
        $this->config = config('Deployment');
    }

    public static function generateKeyPair(): array
    {
        $config = [
            'private_key_bits' => 2048,
            'private_key_type' => OPENSSL_KEYTYPE_RSA,
        ];

        $resource = openssl_pkey_new($config);
        
        openssl_pkey_export($resource, $privateKey);
        
        $publicKeyDetails = openssl_pkey_get_details($resource);
        $publicKey = $publicKeyDetails['key'];

        return [
            'private_key' => base64_encode($privateKey),
            'public_key' => base64_encode($publicKey),
        ];
    }

    public function signData(array $data): string
    {
        $privateKeyPem = base64_decode($this->config->privateKey);
        
        if (empty($privateKeyPem)) {
            throw new \Exception('Private key not configured');
        }

        $privateKey = openssl_pkey_get_private($privateKeyPem);
        
        if ($privateKey === false) {
            throw new \Exception('Invalid private key');
        }

        $jsonData = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        
        $signature = '';
        $success = openssl_sign($jsonData, $signature, $privateKey, OPENSSL_ALGO_SHA256);
        
        if (!$success) {
            throw new \Exception('Failed to sign data');
        }

        return base64_encode($signature);
    }

    public function verifySignature(array $data, string $signature): bool
    {
        $publicKeyPem = base64_decode($this->config->publicKey);
        
        if (empty($publicKeyPem)) {
            throw new \Exception('Public key not configured');
        }

        $publicKey = openssl_pkey_get_public($publicKeyPem);
        
        if ($publicKey === false) {
            throw new \Exception('Invalid public key');
        }

        $jsonData = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        $signatureDecoded = base64_decode($signature);

        $result = openssl_verify($jsonData, $signatureDecoded, $publicKey, OPENSSL_ALGO_SHA256);

        return $result === 1;
    }

    public function createSignedPayload(array $data): array
    {
        $signature = $this->signData($data);
        
        return [
            'data' => $data,
            'signature' => $signature,
            'signed_at' => date('Y-m-d H:i:s'),
        ];
    }

    public function verifySignedPayload(array $payload): bool
    {
        if (!isset($payload['data']) || !isset($payload['signature'])) {
            return false;
        }

        return $this->verifySignature($payload['data'], $payload['signature']);
    }
}
