<?php

declare(strict_types=1);

namespace ServerManager\Services;

use ServerManager\Core\App;
use ServerManager\Core\Database;
use ServerManager\Core\Logger;

class AgentService
{
    private Database $db;
    private Logger $logger;
    private string $basePath;

    public function __construct()
    {
        $this->db = Database::getInstance();
        $this->logger = Logger::getInstance();
        $this->basePath = dirname(__DIR__, 2);
    }

    public function install(int $serverId): array
    {
        $server = $this->db->fetch(
            'SELECT * FROM servers WHERE id = ? AND status = \'active\' AND is_active = 1',
            [$serverId]
        );

        if (!$server) {
            return ['success' => false, 'error' => 'Server not found or inactive'];
        }

        $server = App::getEncryption()->decryptArray($server, ['ssh_password', 'ssh_key']);

        $agentKey = $server['agent_key'];
        $serverUrl = rtrim((App::getConfig()['app']['url'] ?? ''), '/');

        if (empty($serverUrl)) {
            $serverUrl = ($_SERVER['HTTPS'] ?? '' === 'on' ? 'https://' : 'http://') . ($_SERVER['HTTP_HOST'] ?? 'localhost');
        }

        $scriptPath = $this->basePath . '/install/agent-install.sh';

        if (!file_exists($scriptPath)) {
            return ['success' => false, 'error' => 'Agent install script not found'];
        }

        $script = file_get_contents($scriptPath);

        $b64 = base64_encode($script);
        $remoteCommand = sprintf(
            'echo %s | base64 -d > /tmp/_sm_install.sh && chmod +x /tmp/_sm_install.sh && (script -q -c "sudo bash /tmp/_sm_install.sh %s %s" /dev/null < /dev/null 2>/dev/null || sudo bash /tmp/_sm_install.sh %s %s) 2>&1; rc=$?; rm -f /tmp/_sm_install.sh; exit $rc',
            escapeshellarg($b64),
            escapeshellarg($serverUrl),
            escapeshellarg($agentKey),
            escapeshellarg($serverUrl),
            escapeshellarg($agentKey)
        );

        try {
            $ssh = new SSHService();
            if (!$ssh->connect($server, true)) {
                return ['success' => false, 'error' => 'SSH connection failed'];
            }

            $result = $ssh->exec($remoteCommand, 120);
            $ssh->disconnect();

            $output = trim($result['output']);
            $exitStatus = $result['exit_status'] ?? -1;
            $path = '/usr/local/bin/servermanager-agent';

            if ($exitStatus !== 0) {
                $lastLines = implode("\n", array_slice(explode("\n", $output), -20));
                return [
                    'success' => false,
                    'error' => 'Agent installation failed on remote server',
                    'output' => $lastLines,
                ];
            }

            $serverModel = new \ServerManager\Models\Server();
            $serverModel->setAgentInstalled($serverId, true, $path);

            $auditService = new AuditService();
            $auditService->log('agent_installed', 'server', $serverId, [
                'name' => $server['name'],
                'path' => $path,
            ]);

            return ['success' => true, 'path' => $path, 'output' => $output];
        } catch (\Throwable $e) {
            $this->logger->error("Agent install failed for server {$serverId}: " . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }

    public function uninstall(int $serverId): array
    {
        $server = $this->db->fetch(
            'SELECT * FROM servers WHERE id = ? AND status = \'active\' AND is_active = 1',
            [$serverId]
        );

        if (!$server) {
            return ['success' => false, 'error' => 'Server not found or inactive'];
        }

        $server = App::getEncryption()->decryptArray($server, ['ssh_password', 'ssh_key']);

        $scriptPath = $this->basePath . '/install/agent-uninstall.sh';

        if (!file_exists($scriptPath)) {
            return ['success' => false, 'error' => 'Agent uninstall script not found'];
        }

        $script = file_get_contents($scriptPath);

        $remoteCommand = sprintf(
            'echo %s | base64 -d > /tmp/_sm_uninstall.sh && chmod +x /tmp/_sm_uninstall.sh && (script -q -c "sudo bash /tmp/_sm_uninstall.sh" /dev/null < /dev/null 2>/dev/null || sudo bash /tmp/_sm_uninstall.sh) 2>&1; rc=$?; rm -f /tmp/_sm_uninstall.sh; exit $rc',
            escapeshellarg(base64_encode($script))
        );

        try {
            $ssh = new SSHService();
            if (!$ssh->connect($server, true)) {
                return ['success' => false, 'error' => 'SSH connection failed'];
            }

            $result = $ssh->exec($remoteCommand, 60);
            $ssh->disconnect();

            $output = trim($result['output']);
            $exitStatus = $result['exit_status'] ?? -1;

            $serverModel = new \ServerManager\Models\Server();
            $serverModel->setAgentInstalled($serverId, false, null);

            $auditService = new AuditService();
            $auditService->log('agent_uninstalled', 'server', $serverId, [
                'name' => $server['name'],
            ]);

            if ($exitStatus !== 0) {
                return [
                    'success' => false,
                    'error' => 'Agent uninstallation may have failed on remote server',
                    'output' => $output,
                ];
            }

            return ['success' => true, 'output' => $output];
        } catch (\Throwable $e) {
            $this->logger->error("Agent uninstall failed for server {$serverId}: " . $e->getMessage());
            $serverModel = new \ServerManager\Models\Server();
            $serverModel->setAgentInstalled($serverId, false, null);
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
}
