<?php

declare(strict_types=1);

namespace ServerManager\Services;

class PermissionValidator
{
    private SSHService $ssh;

    public function __construct()
    {
        $this->ssh = new SSHService();
    }

    public function validate(array $serverConfig, array $permissions): array
    {
        try {
            if (!$this->ssh->connect($serverConfig, true)) {
                return [
                    'passed' => false,
                    'results' => [],
                    'error' => 'Could not connect to the remote server. Please check the connection details.',
                ];
            }
        } catch (\Throwable $e) {
            return [
                'passed' => false,
                'results' => [],
                'error' => 'SSH connection failed: ' . $e->getMessage(),
            ];
        }

        $results = [];

        foreach ($permissions as $index => $perm) {
            if (empty($perm['type']) || !isset($perm['value'])) {
                continue;
            }

            $type = $perm['type'];
            $value = $perm['value'];
            $description = $perm['description'] ?? '';

            $command = $this->buildCheckCommand($type, $value);

            try {
                $output = $this->ssh->exec($command);
                $passed = $this->evaluateResult($type, $output);
                $results[] = [
                    'type' => $type,
                    'value' => $value,
                    'description' => $description,
                    'passed' => $passed,
                    'message' => $passed ? 'Permission verified' : ($type === 'sudo' ? 'Passwordless sudo is not available' : 'Permission not granted: ' . trim($output['output'] ?? '')),
                ];
            } catch (\Throwable $e) {
                $results[] = [
                    'type' => $type,
                    'value' => $value,
                    'description' => $description,
                    'passed' => false,
                    'message' => 'Check failed: ' . $e->getMessage(),
                ];
            }
        }

        $this->ssh->disconnect();

        $allPassed = !empty($results) && empty(array_filter($results, fn($r) => !$r['passed']));

        return [
            'passed' => $allPassed,
            'results' => $results,
            'error' => null,
        ];
    }

    private function buildCheckCommand(string $type, string $value): string
    {
        return match ($type) {
            'sudo' => 'sudo -n true 2>&1 && echo "OK" || echo "FAIL"',
            'command' => sprintf('command -v %s 2>/dev/null && echo "OK" || echo "FAIL"', escapeshellarg($value)),
            'file_read' => sprintf('test -r %s 2>/dev/null && echo "OK" || echo "FAIL"', escapeshellarg($value)),
            'file_write' => sprintf('test -w %s 2>/dev/null && echo "OK" || echo "FAIL"', escapeshellarg($value)),
            'custom' => sprintf('%s 2>&1; echo "EXIT:$?"', $value),
            default => 'echo "FAIL"',
        };
    }

    private function evaluateResult(string $type, array $output): bool
    {
        $exitCode = $output['exit_status'] ?? 1;
        $stdout = trim($output['output'] ?? '');

        if ($type === 'custom') {
            return $exitCode === 0;
        }

        return $exitCode === 0 && str_contains($stdout, 'OK');
    }
}
