<?php

namespace _121Digital\Connect\Admin\Themes\Services;

/**
 * ThemesService - WordPress Theme Management Service
 *
 * Handles all operations related to the REG121 BuilderPro Base Theme including:
 * - Installation from remote sources
 * - Activation and theme switching
 * - Cleanup of duplicate and orphaned themes
 * - Theme cache management
 * - Theme status checking and validation
 *
 * @package    _121Digital\Connect
 * @subpackage Admin\Themes\Services
 * @since      1.0.0
 * @author     121 Digital
 */
class ThemesService
{
    /**
     * The display name of the BuilderPro Base Theme
     * @var string
     */
    private static $_baseThemeName = 'BuilderPro Base Theme';

    /**
     * Remote URL for downloading the BuilderPro Base Theme zip file
     * @var string
     */
    private static $_baseThemeInstallUrl = 'https://wp-update-service.121domains.co.uk/hellobuilder/builds/REG121_Base-Theme.zip';

    /**
     * Default theme slug prefix for BuilderPro Base Theme installations
     * @var string
     */
    private static $_baseThemeSlug = 'reg121-builderpro-base-theme';

    /**
     * Check if the site has multiple themes installed
     *
     * Useful for determining whether theme management options should be displayed
     * and for conditional logic in theme-related operations.
     *
     * @return bool True if more than one theme is installed, false otherwise
     * @since 1.0.0
     */
    public static function siteHasMultipleThemes(): bool
    {
        $themes = wp_get_themes();
        return count($themes) > 1;
    }

    /**
     * Check if the currently active theme is the BuilderPro Base Theme
     *
     * Compares the active theme's name with the expected BuilderPro Base Theme name
     * to determine if the correct theme is currently activated.
     *
     * @return bool True if BuilderPro Base Theme is active, false otherwise
     * @since 1.0.0
     */
    public static function currentThemeIsBuilderProBaseTheme(): bool
    {
        $currentTheme = wp_get_theme();
        return $currentTheme->get('Name') === self::$_baseThemeName;
    }

    /**
     * Check if the BuilderPro Base Theme is installed (regardless of activation status)
     *
     * Scans all installed themes to determine if any theme matches the BuilderPro
     * Base Theme name, indicating it's available for activation.
     *
     * @return bool True if BuilderPro Base Theme is installed, false otherwise
     * @since 1.0.0
     */
    public static function builderProBaseThemeIsInstalled(): bool
    {
        $themes = wp_get_themes();
        foreach ($themes as $theme) {
            if ($theme->get('Name') === self::$_baseThemeName) {
                return true;
            }
        }
        return false;
    }

    /**
     * Get the version number of the installed BuilderPro Base Theme
     *
     * Retrieves the version string from the theme's style.css header if the theme
     * is installed. Useful for version checking and update notifications.
     *
     * @return string|null Theme version string if installed, null if not found
     * @since 1.0.0
     */
    public static function getBuilderProBaseThemeVersion(): ?string
    {
        $themes = wp_get_themes();
        foreach ($themes as $theme) {
            if ($theme->get('Name') === self::$_baseThemeName) {
                return $theme->get('Version');
            }
        }
        return null;
    }

    /**
     * Refresh WordPress theme cache and clean up orphaned theme references
     *
     * Performs a comprehensive cleanup of WordPress theme caches and validates
     * that the currently active theme actually exists in the filesystem.
     *
     * This method:
     * - Clears all WordPress theme-related transients and caches
     * - Forces WordPress to re-scan the themes directory
     * - Validates that the active theme still exists
     * - Automatically switches to first available theme if active theme is missing
     *
     * @return void
     * @since 1.0.0
     * @throws None - Handles all errors gracefully
     */
    public static function refreshThemeCache(): void
    {
        // Clear WordPress theme cache
        delete_site_transient('theme_roots');
        delete_transient('theme_roots');

        // Clear the themes cache
        wp_cache_delete('themes', 'themes');

        // Force WordPress to re-scan the themes directory
        search_theme_directories(true);

        // Clean up any orphaned theme options that might reference deleted themes
        $current_theme = get_option('stylesheet');
        $template = get_option('template');

        // Check if the current theme actually exists
        if (!file_exists(get_theme_root() . '/' . $current_theme)) {
            // Reset to a default theme if current theme doesn't exist
            $available_themes = wp_get_themes();
            if (!empty($available_themes)) {
                $first_theme = array_keys($available_themes)[0];
                update_option('stylesheet', $first_theme);
                update_option('template', $first_theme);
            }
        }
    }

    /**
     * Remove all themes except the REG121 BuilderPro Base Theme
     *
     * Performs a cleanup operation to remove all installed themes except for
     * the designated REG121 BuilderPro Base Theme. This ensures there are no
     * theme conflicts and maintains a clean theme environment for the network.
     * The operation refreshes the theme cache before deletion to ensure accuracy.
     *
     * This method is typically called during theme installation when the user
     * opts to clean up existing themes, or during maintenance operations to
     * enforce theme consistency across the network.
     *
     * @return void
     * @throws None - Uses WordPress delete_theme() which handles errors internally
     * @since 1.0.0
     */
    public static function deletePreviousThemes(): void
    {
        // First refresh the cache to get accurate theme list
        self::refreshThemeCache();

        $themes = wp_get_themes();
        foreach ($themes as $themeSlug => $theme) {
            if ($theme->get('Name') !== self::$_baseThemeName) {
                // Delete the theme
                delete_theme($themeSlug);
            }
        }
    }

    /**
     * Install the REG121 BuilderPro Base Theme from remote URL
     *
     * Downloads and installs the BuilderPro Base Theme from the predefined remote URL.
     * This method handles the complete installation process including:
     * - Duplicate installation prevention
     * - Remote file download using WordPress HTTP API
     * - ZIP file extraction to themes directory
     * - Proper directory structure handling (moves files from subdirectories if needed)
     * - Cache refresh after installation
     * - Cleanup of temporary files
     *
     * The theme is installed with a timestamped directory name to prevent conflicts
     * and ensure uniqueness across multiple installations.
     *
     * @return void
     * @throws \Exception If download fails, extraction fails, or theme already exists
     * @since 1.0.0
     */
    public static function installBuilderProBaseTheme(): void
    {
        // First refresh cache to get accurate theme list
        self::refreshThemeCache();

        // Check if theme is already installed to prevent duplicates
        if (self::builderProBaseThemeIsInstalled()) {
            throw new \Exception('BuilderPro Base Theme is already installed.');
        }

        $themeUrl = self::$_baseThemeInstallUrl;

        // Use the WordPress HTTP API to download the theme zip file
        $response = wp_remote_get($themeUrl);
        if (is_wp_error($response)) {
            throw new \Exception('Failed to download theme: ' . $response->get_error_message());
        }
        $zipData = wp_remote_retrieve_body($response);
        $uploadDir = wp_upload_dir();
        $zipPath = $uploadDir['path'] . '/builderpro-base-theme.zip';
        file_put_contents($zipPath, $zipData);

        // Use the WordPress Filesystem API to unzip and install the theme
        require_once ABSPATH . 'wp-admin/includes/file.php';
        WP_Filesystem();

        // Create a unique theme directory name
        $theme_slug = self::$_baseThemeSlug . '-' . time();
        $theme_destination = get_theme_root() . '/' . $theme_slug;

        // Ensure the destination directory doesn't exist
        if (file_exists($theme_destination)) {
            throw new \Exception('Theme directory already exists: ' . $theme_slug);
        }

        // Create the theme directory
        if (!wp_mkdir_p($theme_destination)) {
            throw new \Exception('Failed to create theme directory: ' . $theme_slug);
        }

        // Extract the zip file to the theme directory
        $unzipResult = unzip_file($zipPath, $theme_destination);
        if (is_wp_error($unzipResult)) {
            // Clean up the directory if extraction failed
            wp_delete_file($theme_destination);
            throw new \Exception('Failed to unzip theme: ' . $unzipResult->get_error_message());
        }

        // Check if files were extracted to a subdirectory (common with zip files)
        $extracted_files = scandir($theme_destination);
        $subdirectories = array_filter($extracted_files, function ($item) use ($theme_destination) {
            return $item !== '.' && $item !== '..' && is_dir($theme_destination . '/' . $item);
        });

        // If there's only one subdirectory, move its contents up one level
        if (count($subdirectories) === 1 && count(array_filter($extracted_files, function ($item) {
            return $item !== '.' && $item !== '..' && !is_dir($theme_destination . '/' . $item);
        })) === 0) {
            $subdirectory = reset($subdirectories);
            $source_dir = $theme_destination . '/' . $subdirectory;

            // Move all files from subdirectory to theme root
            $files = scandir($source_dir);
            foreach ($files as $file) {
                if ($file !== '.' && $file !== '..') {
                    rename($source_dir . '/' . $file, $theme_destination . '/' . $file);
                }
            }

            // Remove the empty subdirectory
            rmdir($source_dir);
        }

        // Clean up the downloaded zip file
        unlink($zipPath);

        // Refresh cache after installation
        self::refreshThemeCache();
    }

    /**
     * Activate the REG121 BuilderPro Base Theme
     *
     * Searches through all installed themes to find the BuilderPro Base Theme by name
     * and activates it as the current theme. This method handles the theme switching
     * process and ensures the correct theme is activated regardless of its directory slug.
     *
     * The method iterates through all available themes, matches by theme name rather
     * than directory slug (since the directory may have timestamps), and uses WordPress's
     * switch_theme() function to properly activate the theme.
     *
     * @return void
     * @throws None - Fails silently if theme is not found
     * @since 1.0.0
     */
    public static function activateBuilderProBaseTheme(): void
    {
        $themeSlug = '';
        $themes = wp_get_themes();
        foreach ($themes as $slug => $theme) {
            if ($theme->get('Name') === self::$_baseThemeName) {
                $themeSlug = $slug;
                break;
            }
        }
        if ($themeSlug) {
            switch_theme($themeSlug);
        }
    }

    /**
     * Clean up orphaned and duplicate theme installations
     *
     * Performs comprehensive theme cleanup by removing duplicate BuilderPro Base Theme
     * installations and clearing orphaned theme references. This maintenance operation
     * is useful when multiple theme installations have occurred or when themes show
     * inconsistent states in the WordPress admin.
     *
     * The cleanup process includes:
     * - Identifying all BuilderPro Base Theme installations
     * - Preserving the active theme or the first installation found
     * - Removing duplicate installations safely
     * - Switching active theme if a duplicate was active
     * - Clearing all theme caches for consistency
     * - Providing detailed reporting of all actions taken
     *
     * @return array Detailed cleanup report with before/after counts and actions taken
     * @since 1.0.0
     */
    public static function cleanupOrphanedThemes(): array
    {
        $cleanup_report = [
          'themes_before' => 0,
          'themes_after' => 0,
          'duplicates_removed' => 0,
          'orphaned_removed' => 0,
          'cache_cleared' => true,
          'actions_taken' => []
        ];

        // Get initial theme list
        $themes_before = wp_get_themes();
        $cleanup_report['themes_before'] = count($themes_before);

        // Find all BuilderPro Base Theme installations
        $builderpro_themes = [];
        $active_theme = get_stylesheet();

        foreach ($themes_before as $slug => $theme) {
            if ($theme->get('Name') === self::$_baseThemeName) {
                $builderpro_themes[$slug] = $theme;
            }
        }

        // If we have multiple BuilderPro Base Theme installations, remove duplicates
        if (count($builderpro_themes) > 1) {
            $cleanup_report['actions_taken'][] = 'Found ' . count($builderpro_themes) . ' BuilderPro Base Theme installations';

            // Keep the active one if it's BuilderPro, otherwise keep the first one
            $theme_to_keep = null;
            if (isset($builderpro_themes[$active_theme])) {
                $theme_to_keep = $active_theme;
                $cleanup_report['actions_taken'][] = 'Keeping active BuilderPro theme: ' . $active_theme;
            } else {
                $theme_to_keep = array_keys($builderpro_themes)[0];
                $cleanup_report['actions_taken'][] = 'Keeping first BuilderPro theme: ' . $theme_to_keep;
            }

            // Remove all other BuilderPro installations
            foreach ($builderpro_themes as $slug => $theme) {
                if ($slug !== $theme_to_keep) {
                    $cleanup_report['actions_taken'][] = 'Removing duplicate BuilderPro theme: ' . $slug;

                    // If this duplicate is currently active, switch to the one we're keeping
                    if ($slug === $active_theme) {
                        switch_theme($theme_to_keep);
                        $cleanup_report['actions_taken'][] = 'Switched active theme to: ' . $theme_to_keep;
                    }

                    // Delete the duplicate theme
                    $delete_result = delete_theme($slug);
                    if (is_wp_error($delete_result)) {
                        $cleanup_report['actions_taken'][] = 'Failed to delete ' . $slug . ': ' . $delete_result->get_error_message();
                    } else {
                        $cleanup_report['duplicates_removed']++;
                        $cleanup_report['actions_taken'][] = 'Successfully deleted: ' . $slug;
                    }
                }
            }
        }

        // Clear all theme caches
        self::refreshThemeCache();
        $cleanup_report['actions_taken'][] = 'Cleared theme caches';

        // Get final theme count
        $themes_after = wp_get_themes();
        $cleanup_report['themes_after'] = count($themes_after);
        $cleanup_report['orphaned_removed'] = $cleanup_report['themes_before'] - $cleanup_report['themes_after'] - $cleanup_report['duplicates_removed'];

        return $cleanup_report;
    }
}
