<?php

namespace VulnTitan\Services;

use FilesystemIterator;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;

class BaselineBuilder
{
    protected static array $skipExtensions = [
        'gif', 'png', 'jpg', 'jpeg', 'jpe', 'jfif', 'pjpeg', 'pjp', 'svg', 'webp', 'bmp', 'ico', 'avif', 'tif', 'tiff', 'heic', 'heif',
        'css', 'scss',
        'log', 'queue', 'zip', 'tar', 'gz', 'rar', '7z',
        'map', 'json', 'md', 'txt', 'csv',
        'lock', 'sqlite', 'db', 'ds_store',
        'woff', 'woff2', 'ttf', 'otf', 'eot',
    ];

    protected static array $skipFolders = [
        'node_modules',
        'vendor',
        '.git',
        '.svn',
        'uploads',
        'cache',
        'backups',
    ];

    public static function build(): array
    {
        $baseline = [];

        // Plugins
        foreach (self::getPluginFiles() as $path) {
            $baseline[$path] = sha1_file(ABSPATH . $path);
        }

        // MU Plugins
        foreach (self::getMuPluginFiles() as $path) {
            $baseline[$path] = sha1_file(ABSPATH . $path);
        }

        // Themes
        foreach (self::getThemeFiles() as $path) {
            $baseline[$path] = sha1_file(ABSPATH . $path);
        }

        // High-risk root files (if present)
        foreach (self::getExtraRootFiles() as $path) {
            $baseline[$path] = sha1_file(ABSPATH . $path);
        }

        return $baseline;
    }

    protected static function ensureStorageFolder(): void
    {
        $dir = dirname(VULNTITAN_BASELINE_FILE);
        if (!is_dir($dir)) {
            wp_mkdir_p($dir);
        }
    }

    public static function save(): bool
    {
        self::ensureStorageFolder();

        $data = self::build();
        return file_put_contents(VULNTITAN_BASELINE_FILE, json_encode($data, JSON_PRETTY_PRINT)) !== false;
    }

    public static function exists(): bool
    {
        return file_exists(VULNTITAN_BASELINE_FILE);
    }

    public static function load(): array
    {
        if (!self::exists()) return [];
        return json_decode(file_get_contents(VULNTITAN_BASELINE_FILE), true) ?? [];
    }

    protected static function getPluginFiles(): array
    {
        $paths = [];
        if (!function_exists('get_plugins')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        $plugins = get_plugins();
        foreach ($plugins as $file => $_) {
            $full = WP_PLUGIN_DIR . '/' . $file;
            if (!is_file($full)) {
                $dir = WP_PLUGIN_DIR . '/' . dirname($file);
                $paths = array_merge($paths, self::getAllFiles($dir));
                continue;
            }

            if (dirname($file) === '.') {
                $paths[] = self::normalizePath($full);
                continue;
            }

            $dir = dirname($full);
            $paths = array_merge($paths, self::getAllFiles($dir));
        }
        return $paths;
    }

    protected static function getThemeFiles(): array
    {
        $paths = [];
        foreach (wp_get_themes() as $theme) {
            $paths = array_merge($paths, self::getAllFiles($theme->get_stylesheet_directory()));
        }
        return $paths;
    }

    protected static function getMuPluginFiles(): array
    {
        if (!defined('WPMU_PLUGIN_DIR') || !is_dir(WPMU_PLUGIN_DIR)) {
            return [];
        }

        return self::getAllFiles(WPMU_PLUGIN_DIR);
    }

    protected static function getExtraRootFiles(): array
    {
        $paths = [];
        $candidates = [
            'wp-config.php',
            '.htaccess',
            'web.config',
        ];

        foreach ($candidates as $path) {
            if (file_exists(ABSPATH . $path)) {
                $paths[] = $path;
            }
        }

        return $paths;
    }

    protected static function getAllFiles(string $dir): array
    {
        $files = [];
        if (!is_dir($dir)) return $files;

        $directoryIterator = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
        $filter = new \RecursiveCallbackFilterIterator(
            $directoryIterator,
            function ($current) {
                if ($current->isDir()) {
                    return !in_array($current->getFilename(), self::$skipFolders, true);
                }
                return true;
            }
        );
        $rii = new RecursiveIteratorIterator($filter);

        foreach ($rii as $file) {
            if (!$file->isFile()) continue;

            $absPath = $file->getPathname();
            $relPath = self::normalizePath($absPath);

            if (self::shouldSkipByExtension($absPath)) {
                continue;
            }

            $files[] = $relPath;
        }

        return $files;
    }

    protected static function normalizePath(string $path): string
    {
        return ltrim(str_replace(['\\', '//'], '/', str_replace(realpath(ABSPATH), '', realpath($path) ?: $path)), '/');
    }

    protected static function shouldSkipByExtension(string $path): bool
    {
        $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));

        return $extension !== '' && in_array($extension, self::$skipExtensions, true);
    }
}
