<?php

namespace App\Addons\Services;

use Illuminate\Support\Facades\File;

/**
 * Addon Security Validator
 * Validates addon packages for security before installation
 */
class AddonSecurityValidator
{
    /**
     * Validate addon package for security
     *
     * @return array ['valid' => bool, 'errors' => array]
     */
    public function validateAddon(string $addonPath): array
    {
        $errors = [];

        // Check if addon directory exists
        if (! File::isDirectory($addonPath)) {
            return [
                'valid' => false,
                'errors' => ['Addon directory does not exist'],
            ];
        }

        // Check for required files
        $requiredFiles = ['addon.json', 'ServiceProvider.php'];
        foreach ($requiredFiles as $file) {
            if (! File::exists($addonPath.'/'.$file)) {
                $errors[] = "Required file missing: {$file}";
            }
        }

        // Scan for malicious patterns
        $securityScan = $this->scanForMaliciousCode($addonPath);
        if (! $securityScan['safe']) {
            $errors = array_merge($errors, $securityScan['threats']);
        }

        // Check file permissions
        $permissionCheck = $this->checkFilePermissions($addonPath);
        if (! $permissionCheck['valid']) {
            $errors = array_merge($errors, $permissionCheck['errors']);
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
        ];
    }

    /**
     * Scan addon files for malicious code patterns
     *
     * @return array ['safe' => bool, 'threats' => array]
     */
    private function scanForMaliciousCode(string $addonPath): array
    {
        $threats = [];
        $dangerousPatterns = [
            'eval(',
            'base64_decode',
            'exec(',
            'system(',
            'shell_exec',
            'passthru',
            'proc_open',
            'popen',
            'file_get_contents.*http',
            'curl_exec',
            'fopen.*http',
            'include.*http',
            'require.*http',
        ];

        $files = File::allFiles($addonPath);

        foreach ($files as $file) {
            // Skip non-PHP files for code scanning
            if ($file->getExtension() !== 'php') {
                continue;
            }

            $content = File::get($file->getPathname());

            foreach ($dangerousPatterns as $pattern) {
                if (preg_match('/'.$pattern.'/i', $content)) {
                    $threats[] = "Potentially dangerous code found in: {$file->getRelativePathname()} (pattern: {$pattern})";
                }
            }

            // Check for direct database queries without parameter binding
            if (preg_match('/DB::(raw|select|insert|update|delete)\(["\']/', $content)) {
                $threats[] = "Potential SQL injection risk in: {$file->getRelativePathname()}";
            }
        }

        return [
            'safe' => empty($threats),
            'threats' => $threats,
        ];
    }

    /**
     * Check file permissions
     *
     * @return array ['valid' => bool, 'errors' => array]
     */
    private function checkFilePermissions(string $addonPath): array
    {
        $errors = [];

        // Check if directory is readable
        if (! is_readable($addonPath)) {
            $errors[] = 'Addon directory is not readable';
        }

        // Check if directory is writable (should be for installation)
        if (! is_writable($addonPath)) {
            $errors[] = 'Addon directory is not writable';
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
        ];
    }

    /**
     * Validate addon manifest structure
     *
     * @return array ['valid' => bool, 'errors' => array]
     */
    public function validateManifest(array $manifest): array
    {
        $errors = [];
        $requiredFields = ['name', 'version', 'slug', 'description'];

        foreach ($requiredFields as $field) {
            if (! isset($manifest[$field]) || empty($manifest[$field])) {
                $errors[] = "Required manifest field missing: {$field}";
            }
        }

        // Validate version format
        if (isset($manifest['version']) && ! preg_match('/^\d+\.\d+\.\d+$/', $manifest['version'])) {
            $errors[] = 'Invalid version format (must be semver: x.y.z)';
        }

        // Validate slug format
        if (isset($manifest['slug']) && ! preg_match('/^[a-z0-9\-_]+$/', $manifest['slug'])) {
            $errors[] = 'Invalid slug format (only lowercase letters, numbers, hyphens, and underscores allowed)';
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
        ];
    }
}
