<?php

declare(strict_types=1);

namespace App\Framework\Deployment\Ssl\Commands;

use App\Framework\Config\Environment;
use App\Framework\Console\Attributes\ConsoleCommand;
use App\Framework\Console\ConsoleOutput;
use App\Framework\Console\ExitCode;
use App\Framework\Deployment\Ssl\Services\SslCertificateService;
use App\Framework\Deployment\Ssl\ValueObjects\CertificateMode;
use App\Framework\Deployment\Ssl\ValueObjects\SslConfiguration;

/**
 * Console command to initialize SSL certificates using Let's Encrypt
 */
#[ConsoleCommand(
    name: 'ssl:init',
    description: 'Initialize Let\'s Encrypt SSL certificates for configured domain'
)]
final readonly class SslInitCommand
{
    public function __construct(
        private SslCertificateService $sslService,
        private Environment $environment,
        private ConsoleOutput $output
    ) {}

    public function execute(): ExitCode
    {
        $this->output->writeLine('🔒 Initializing SSL Certificates...');
        $this->output->writeLine('');

        try {
            // Load configuration from environment
            $config = SslConfiguration::fromEnvironment($this->environment);

            // Display configuration
            $this->displayConfiguration($config);

            // Test configuration first
            $this->output->write('Testing configuration... ');
            if (!$this->sslService->test($config)) {
                $this->output->writeLine('❌ Failed');
                $this->output->writeLine('');
                $this->output->writeLine('Configuration test failed. Please check:');
                $this->output->writeLine('  - Domain DNS is correctly configured');
                $this->output->writeLine('  - Webroot directory is accessible');
                $this->output->writeLine('  - Port 80 is open and reachable');
                return ExitCode::FAILURE;
            }
            $this->output->writeLine('✅ Passed');
            $this->output->writeLine('');

            // Obtain certificate
            $this->output->writeLine('Obtaining certificate...');
            $status = $this->sslService->obtain($config);

            $this->output->writeLine('');
            $this->output->writeLine('✅ Certificate obtained successfully!');
            $this->output->writeLine('');

            // Display certificate status
            $this->displayCertificateStatus($status);

            if ($config->mode->isStaging()) {
                $this->output->writeLine('');
                $this->output->writeLine('⚠️  Note: Staging mode certificate obtained (for testing)');
                $this->output->writeLine('   Set LETSENCRYPT_STAGING=0 in .env for production certificates');
            }

            $this->output->writeLine('');
            $this->output->writeLine('Next steps:');
            $this->output->writeLine('  1. Reload/restart your web server');
            $this->output->writeLine('  2. Test HTTPS access to your domain');
            $this->output->writeLine('  3. Set up automatic renewal (ssl:renew)');

            return ExitCode::SUCCESS;

        } catch (\Exception $e) {
            $this->output->writeLine('');
            $this->output->writeLine('❌ Error: ' . $e->getMessage());
            $this->output->writeLine('');
            return ExitCode::FAILURE;
        }
    }

    private function displayConfiguration(SslConfiguration $config): void
    {
        $this->output->writeLine('Configuration:');
        $this->output->writeLine('  Domain: ' . $config->domain->value);
        $this->output->writeLine('  Email: ' . $config->email->value);
        $this->output->writeLine('  Mode: ' . $config->mode->value . ' (' . $config->mode->getDescription() . ')');
        $this->output->writeLine('  Webroot: ' . $config->certbotWwwDir->toString());
        $this->output->writeLine('  Config Dir: ' . $config->certbotConfDir->toString());
        $this->output->writeLine('');
    }

    private function displayCertificateStatus($status): void
    {
        $this->output->writeLine('Certificate Information:');
        $this->output->writeLine('  Valid From: ' . $status->notBefore?->format('Y-m-d H:i:s') ?? 'N/A');
        $this->output->writeLine('  Valid Until: ' . $status->notAfter?->format('Y-m-d H:i:s') ?? 'N/A');
        $this->output->writeLine('  Days Until Expiry: ' . ($status->daysUntilExpiry ?? 'N/A'));
        $this->output->writeLine('  Issuer: ' . ($status->issuer ?? 'N/A'));
        $this->output->writeLine('  Subject: ' . ($status->subject ?? 'N/A'));
        $this->output->writeLine('  Health Status: ' . $status->getHealthStatus());
    }
}
