<?php 
namespace Lcmigrator\LcMigrator\Importer\Manager;

use Exception;
use Lcmigrator\LcMigrator\Database\DatabaseConnection;
use Lcmigrator\LcMigrator\Importer\Database\Importer;
use Lcmigrator\LcMigrator\Importer\QueryParser\SqlParser;
use Lcmigrator\LcMigrator\Logger\Logger;
use ZipArchive;

class Manager{
    private Logger $logger;
    private string $upload_dir;
    private string $temp_dir;

    public function __construct(Logger $logger){
        $this->logger = $logger;
        $this->logger->info("Importer Called Import Manager");
        
        // Create unique temporary directory for imports
        $unique_id = uniqid('import_');
        $this->temp_dir = wp_upload_dir()['basedir'] . '/temp_' . $unique_id . '/';
        $this->upload_dir = $this->temp_dir . 'backup-imports/';
        
        // Create temp directories
        wp_mkdir_p($this->temp_dir);
        wp_mkdir_p($this->upload_dir);
    }

    public function start_import(string $fileLocation){
        $this->logger->info('Starting import process');
        try {
            // Copy zip to temp location first
            $temp_zip = $this->temp_dir . basename($fileLocation);
            rename($fileLocation, $temp_zip);
            
            // Process from temp location
            $this->extract_backup($temp_zip);
            
            // Cleanup temp directory when done
            $this->cleanup_temp_dir();
            
        } catch (Exception $e) {
            // Cleanup on error
            $this->cleanup_temp_dir();
            throw $e;
        }
    }

    private function extract_backup($zip_path)
    {
        $zip = new ZipArchive();
        
        $this->logger->log("Extracting backup file: {$zip_path}");

        if ($zip->open($zip_path) === TRUE) {
            // Extract to temporary directory
            $extract_path = $this->upload_dir . 'extracted_backup/';
            $this->logger->log("Temporary Extract Success : {$extract_path}");
            wp_mkdir_p($extract_path);

            // Extract with preservation of directory structure
            $zip->extractTo($extract_path);
            $zip->close();

            try {

                // Replace wp-content with preservation
                $this->logger->log("Replacing wp-content directory");
                $this->replace_wp_content($extract_path);
                $this->logger->log("wp-content Replacement Completed");


                $this->logger->log("Starting Database Import");

                $databaseConnection = new DatabaseConnection(array(
                    "host" => DB_HOST,
                    "user" => DB_USER,
                    "password" => DB_PASSWORD,
                    "database" => DB_NAME,
                ), $this->logger);
                $sqlParser = new SqlParser($this->logger);
                $databaseImporter = new Importer($databaseConnection, $sqlParser, $this->logger);
                $this->logger->log("Site URL: " . get_site_url());
                $this->logger->log("Sql File Path: " . $extract_path . 'database_backup.sql');
                $this->logger->log("Site Info: " . $extract_path . 'site_info.json');
                $siteInfo = json_decode(file_get_contents($extract_path . 'site_info.json'), true);
                $databaseImporter->importDatabase($extract_path . 'database_backup.sql', $siteInfo['site_url'], get_site_url());
                $this->logger->log("Database Import Completed");
                return true;
            } catch (Exception $e) {
                $this->logger->log("Import Error: " . $e->getMessage(), 'error');
                // Log and handle any import errors
                error_log('Backup Import Error: ' . $e->getMessage());
                wp_die('Backup import failed: ' . esc_html($e->getMessage()));
            }
        } else {
            $this->logger->log("Failed to open backup zip file", 'error');
            wp_die('Unable to open backup zip file.');
        }
    }

    private function replace_wp_content($extract_path) 
    {
        $current_wp_content = WP_CONTENT_DIR;
        $backup_wp_content = $extract_path . 'wp-content/';
    
        // Priority folders that need special handling
        $priority_folders = [
            'plugins',
            'uploads'
        ];

        // Protected folders that should not be replaced
        $protected_folders = [
            'lc-migrator'
        ];
    
        if (is_dir($backup_wp_content)) {
            $backup_items = array_diff(scandir($backup_wp_content), ['.', '..']);
            
            foreach ($backup_items as $item) {
                // Skip protected folders
                if (in_array($item, $protected_folders)) {
                    continue;
                }

                $source_path = rtrim($backup_wp_content, '/') . '/' . $item;
                $destination_path = rtrim($current_wp_content, '/') . '/' . $item;
    
                if (in_array($item, $priority_folders)) {
                    // For priority folders, merge contents instead of replacing
                    if (is_dir($source_path) && is_dir($destination_path)) {
                        $this->merge_directory($source_path, $destination_path);
                    }
                } else {
                    // For non-priority items, replace completely
                    if (file_exists($destination_path)) {
                        if (is_dir($destination_path)) {
                            $this->delete_directory($destination_path);
                        } else {
                            unlink($destination_path);
                        }
                    }
    
                    if (is_dir($source_path)) {
                        $this->copy_directory($source_path, $destination_path);
                    } else {
                        copy($source_path, $destination_path);
                    }
                }
            }
        }
    }
    
    private function merge_directory($source, $destination) 
    {
        if (!file_exists($destination)) {
            wp_mkdir_p($destination);
        }
    
        $files = array_diff(scandir($source), ['.', '..']);
        
        foreach ($files as $file) {
            $src_file = rtrim($source, '/') . '/' . $file;
            $dest_file = rtrim($destination, '/') . '/' . $file;
    
            if (is_dir($src_file)) {
                // Recursively merge subdirectories
                $this->merge_directory($src_file, $dest_file);
            } else {
                // For files, only copy if they don't exist or are different
                if (!file_exists($dest_file) || md5_file($src_file) !== md5_file($dest_file)) {
                    copy($src_file, $dest_file);
                }
            }
        }
    }
    
    private function copy_directory($source, $destination) 
    {
        if (!file_exists($destination)) {
            wp_mkdir_p($destination);
        }
    
        $files = array_diff(scandir($source), ['.', '..']);
        
        foreach ($files as $file) {
            $src_file = rtrim($source, '/') . '/' . $file;
            $dest_file = rtrim($destination, '/') . '/' . $file;
    
            if (is_dir($src_file)) {
                $this->copy_directory($src_file, $dest_file);
            } else {
                copy($src_file, $dest_file);
            }
        }
    }

    private function delete_directory($path)
    {
        if (!is_dir($path)) return;

        $files = array_diff(scandir($path), ['.', '..']);

        foreach ($files as $file) {
            $file_path = $path . '/' . $file;

            // Skip certain critical directories
            if (in_array($file, ['plugins', 'uploads', 'languages'])) continue;

            if (is_dir($file_path)) {
                $this->delete_directory($file_path);
            } else {
                if (file_exists($file_path)) {
                    @unlink($file_path);
                }
            }
        }

        // Only remove directory if not a critical system folder and empty
        $critical_dirs = ['plugins', 'uploads', 'languages'];
        if (!in_array(basename($path), $critical_dirs)) {
            // Check if directory is empty before trying to remove
            $remaining_files = array_diff(scandir($path), ['.', '..']);
            if (empty($remaining_files)) {
                @rmdir($path);
            }
        }
    }

    private function cleanup_temp_dir() 
    {
        // Recursively remove temporary directory and all contents
        if (is_dir($this->temp_dir)) {
            lc_migrator_recursive_directory_delete($this->temp_dir);
        }
    }
}
