<?php

declare(strict_types=1);

namespace App\Domain\MailServer\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;

/**
 * MailServerManager — install + switch işlemleri.
 *
 * WebServerManager ile aynı pattern. Driver değişiklikleri:
 * - config('mailserver.driver') güncellenir
 * - mail.* config'leri yeni driver'ın laravelConfig()'inden alınır
 * - Eski servis durdurulur, yeni servis başlatılır
 */
class MailServerManager
{
    public function __construct(private readonly MailServerFactory $factory) {}

    public function install(string $driver): array
    {
        $adapter = $this->factory->makeByKey($driver);
        if (! $adapter) {
            return ['ok' => false, 'error' => "Bilinmeyen driver: $driver"];
        }

        if ($adapter->isInstalled()) {
            return ['ok' => true, 'message' => $adapter->name() . ' zaten kurulu', 'already_installed' => true];
        }

        $this->logAudit('mailserver.install.start', ['driver' => $driver]);

        $result = $adapter->install();

        $this->logAudit(
            $result['ok'] ? 'mailserver.install.success' : 'mailserver.install.failed',
            ['driver' => $driver, 'output' => substr($result['output'] ?? '', 0, 500)]
        );

        return $result;
    }

    public function switchTo(string $newDriver): array
    {
        $newAdapter = $this->factory->makeByKey($newDriver);
        if (! $newAdapter) {
            return ['ok' => false, 'error' => "Bilinmeyen driver: $newDriver"];
        }

        if (! $newAdapter->isInstalled() && $newDriver !== 'relay' && $newDriver !== 'none') {
            return [
                'ok' => false,
                'error' => $newAdapter->name() . ' kurulu değil. Önce kurulum yapın.',
                'requires_install' => true,
            ];
        }

        $currentDriver = $this->factory->activeKey();
        if ($currentDriver === $newDriver) {
            return ['ok' => true, 'message' => 'Zaten aktif: ' . $newAdapter->name(), 'no_change' => true];
        }

        $oldAdapter = $this->factory->makeByKey($currentDriver);

        $this->logAudit('mailserver.switch.start', ['from' => $currentDriver, 'to' => $newDriver]);

        try {
            // Yeni servis varsa enable + start
            if ($newAdapter->isInstalled() && $newAdapter->serviceName()) {
                $newAdapter->enable();
                $newAdapter->start();
            }

            // Eski servisi durdur (sadece local servis ise)
            if ($oldAdapter && $oldAdapter->isInstalled() && $oldAdapter->serviceName() && $oldAdapter->isRunning()) {
                $oldAdapter->stop();
            }

            $this->persistDriver($newDriver);

            $this->logAudit('mailserver.switch.success', ['from' => $currentDriver, 'to' => $newDriver]);

            return [
                'ok' => true,
                'message' => "Aktif mail sunucusu artık {$newAdapter->name()}.",
                'new_driver' => $newDriver,
            ];
        } catch (\Throwable $e) {
            $this->logAudit('mailserver.switch.failed', [
                'from' => $currentDriver,
                'to' => $newDriver,
                'error' => $e->getMessage(),
            ]);

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

    private function persistDriver(string $driver): void
    {
        if (Schema::hasTable('server_settings')) {
            DB::table('server_settings')->updateOrInsert(
                ['key' => 'mailserver_driver'],
                [
                    'group' => 'mailserver',
                    'type' => 'string',
                    'value' => $driver,
                    'updated_at' => now(),
                    'created_at' => now(),
                ]
            );
        }

        try {
            \Artisan::call('config:clear');
        } catch (\Throwable) {
            // ignored
        }
    }

    private function logAudit(string $action, array $payload): void
    {
        try {
            if (Schema::hasTable('license_audit_log')) {
                DB::table('license_audit_log')->insert([
                    'action' => $action,
                    'payload' => json_encode($payload, JSON_UNESCAPED_UNICODE),
                    'success' => ! str_contains($action, 'failed'),
                    'remote_ip' => request()?->ip(),
                    'occurred_at' => now(),
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
            }
        } catch (\Throwable) {
            Log::info("[mailserver-audit] $action", $payload);
        }
    }
}
