<?php

declare(strict_types=1);

namespace App\Framework\Deployment\Ssl\Jobs;

use App\Framework\Config\Environment;
use App\Framework\Deployment\Ssl\Services\SslCertificateService;
use App\Framework\Deployment\Ssl\ValueObjects\SslConfiguration;
use App\Framework\Logging\Logger;
use App\Framework\Worker\Every;
use App\Framework\Worker\Schedule;

/**
 * SSL Certificate Renewal Job
 *
 * Runs daily at 2 AM to check and renew SSL certificates if needed
 */
#[Schedule(at: new Every(days: 1))]
final readonly class SslCertificateRenewalJob
{
    public function __construct(
        private SslCertificateService $sslService,
        private Environment $environment,
        private Logger $logger
    ) {}

    /**
     * Check certificate status and renew if needed
     *
     * @return array<string, mixed>
     */
    public function handle(): array
    {
        try {
            $config = SslConfiguration::fromEnvironment($this->environment);

            $this->logger->info('Running scheduled SSL certificate renewal check', [
                'domain' => $config->domain->value,
            ]);

            // Get current certificate status
            $status = $this->sslService->getStatus(
                $config->domain,
                $config->certbotConfDir->toString()
            );

            // Check if certificate exists
            if (!$status->exists) {
                $this->logger->warning('SSL certificate does not exist', [
                    'domain' => $config->domain->value,
                ]);

                return [
                    'success' => false,
                    'reason' => 'certificate_not_found',
                    'domain' => $config->domain->value,
                ];
            }

            // Check if renewal is needed
            if (!$status->needsRenewal()) {
                $this->logger->info('SSL certificate does not need renewal', [
                    'domain' => $config->domain->value,
                    'days_until_expiry' => $status->daysUntilExpiry,
                    'health_status' => $status->getHealthStatus(),
                ]);

                return [
                    'success' => true,
                    'renewed' => false,
                    'reason' => 'not_needed',
                    'domain' => $config->domain->value,
                    'days_until_expiry' => $status->daysUntilExpiry,
                    'health_status' => $status->getHealthStatus(),
                ];
            }

            // Renew certificate
            $this->logger->info('SSL certificate renewal needed, starting renewal', [
                'domain' => $config->domain->value,
                'days_until_expiry' => $status->daysUntilExpiry,
                'is_expired' => $status->isExpired,
                'is_expiring' => $status->isExpiring,
            ]);

            $newStatus = $this->sslService->renew($config);

            $this->logger->info('SSL certificate renewed successfully', [
                'domain' => $config->domain->value,
                'old_expiry' => $status->notAfter?->format('Y-m-d H:i:s'),
                'new_expiry' => $newStatus->notAfter?->format('Y-m-d H:i:s'),
                'new_days_until_expiry' => $newStatus->daysUntilExpiry,
            ]);

            return [
                'success' => true,
                'renewed' => true,
                'domain' => $config->domain->value,
                'old_expiry' => $status->notAfter?->format('Y-m-d H:i:s'),
                'new_expiry' => $newStatus->notAfter?->format('Y-m-d H:i:s'),
                'days_until_expiry' => $newStatus->daysUntilExpiry,
                'health_status' => $newStatus->getHealthStatus(),
            ];

        } catch (\Exception $e) {
            $this->logger->error('Scheduled SSL certificate renewal failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }
}
