<?php

namespace App\Service;

use Symfony\Contracts\HttpClient\HttpClientInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

class NotifuseClient
{
    private const BASE_URI = 'https://notifuse.esy-web.dev/';
    private const NOTIFICATION_ENDPOINT = 'api/notifications';
    private const LOGIN_ENDPOINT = 'api/user.rootSignin'; // New endpoint

    private HttpClientInterface $httpClient;
    private LoggerInterface $logger;
    private ?string $rootEmail; // For login
    private ?string $rootSecretKey; // For signing login request
    private ?string $authToken = null; // Stored after successful login

    public function __construct(
        HttpClientInterface $httpClient,
        LoggerInterface $logger,
        #[Autowire('%env(resolve:NOTIFUSE_ROOT_EMAIL)%')]
        ?string $rootEmail = null,
        #[Autowire('%env(resolve:NOTIFUSE_SECRET_KEY)%')]
        ?string $rootSecretKey = null
    ) {
        $this->httpClient = $httpClient;
        $this->logger = $logger;
        $this->rootEmail = $rootEmail;
        $this->rootSecretKey = $rootSecretKey;
    }

    /**
     * Attempts to log in to the Notifuse API and obtain an authentication token.
     *
     * @return bool True if login is successful and a token is obtained, false otherwise.
     */
    public function login(): bool
    {
        if ($this->authToken !== null) {
            // Already logged in, no need to log in again
            return true;
        }

        if ($this->rootEmail === null || $this->rootSecretKey === null) {
            $this->logger->error('Notifuse root email or secret key is not configured for login.');
            return false;
        }

        $timestamp = time(); // Current Unix timestamp
        $messageToSign = "{$this->rootEmail}:{$timestamp}";
        $signature = hash_hmac('sha256', $messageToSign, $this->rootSecretKey);

        $payload = [
            'email' => $this->rootEmail,
            'timestamp' => $timestamp,
            'signature' => $signature,
        ];

        try {
            $response = $this->httpClient->request('POST', self::BASE_URI . self::LOGIN_ENDPOINT, [
                'headers' => ['Content-Type' => 'application/json'],
                'json' => $payload,
            ]);

            $statusCode = $response->getStatusCode();
            $content = $response->toArray(false);

            if ($statusCode >= 200 && $statusCode < 300 && isset($content['token'])) {
                $this->authToken = $content['token'];
                $this->logger->info('Successfully logged into Notifuse API.');
                return true;
            } else {
                $this->logger->error('Notifuse login failed.', [
                    'statusCode' => $statusCode,
                    'response' => $content,
                ]);
                return false;
            }
        } catch (\Exception $e) {
            $this->logger->error('Exception during Notifuse login: ' . $e->getMessage(), [
                'exception' => $e,
            ]);
            return false;
        }
    }

    /**
     * Sends a notification via the Notifuse API.
     * It will attempt to log in if not already authenticated.
     *
     * @param string $recipient The recipient's identifier (e.g., email, phone number).
     * @param string $subject The subject of the notification.
     * @param string $message The content of the notification.
     * @param string $type The type of notification (e.g., 'email', 'sms').
     * @param array $additionalData Additional data to send with the notification.
     * @return bool True if the notification was sent successfully, false otherwise.
     */
    public function sendNotification(
        string $recipient,
        string $subject,
        string $message,
        string $type,
        array $additionalData = []
    ): bool {
        // Ensure authentication token is available
        if ($this->authToken === null && !$this->login()) {
            $this->logger->error('Cannot send Notifuse notification: failed to authenticate.');
            return false;
        }

        $payload = [
            'recipient' => $recipient,
            'subject' => $subject,
            'message' => $message,
            'type' => $type,
        ];

        if (!empty($additionalData)) {
            $payload = array_merge($payload, $additionalData);
        }

        $headers = [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $this->authToken, // Use the obtained token
        ];

        try {
            $response = $this->httpClient->request('POST', self::BASE_URI . self::NOTIFICATION_ENDPOINT, [
                'headers' => $headers,
                'json' => $payload,
            ]);

            $statusCode = $response->getStatusCode();
            $content = $response->toArray(false);

            if ($statusCode >= 200 && $statusCode < 300) {
                $this->logger->info('Notifuse notification sent successfully.', [
                    'recipient' => $recipient,
                    'type' => $type,
                    'statusCode' => $statusCode,
                    'response' => $content
                ]);
                return true;
            } else {
                $this->logger->error('Failed to send Notifuse notification.', [
                    'recipient' => $recipient,
                    'type' => $type,
                    'statusCode' => $statusCode,
                    'response' => $content
                ]);
                return false;
            }
        } catch (\Exception $e) {
            $this->logger->error('Exception while sending Notifuse notification: ' . $e->getMessage(), [
                'recipient' => $recipient,
                'type' => $type,
                'exception' => $e
            ]);
            return false;
        }
    }
}
