<?php

/**
 * cPanel Backup Importer for WHP - Fixed Version
 * 
 * Uses existing WHP infrastructure for:
 * - Domain management
 * - Site creation  
 * - Database creation (via mysqlmgmt)
 * - MySQL user creation (via mysqlmgmt)
 * - DNS record creation (via PowerDNS)
 */
class CpanelBackupImporter {
    
    private $pdo;
    private $backupPath;
    private $extractPath;
    private $username;
    private $importLog = [];
    private $siteGroups = [];
    private $mysqlMgmt;
    private $powerDNS;
    private $importId;
    
    public function __construct($pdo, $username) {
        $this->pdo = $pdo;
        $this->username = $username;
        
        // Initialize WHP components
        require_once('/docker/whp/web/libs/mysqlmgmt.php');
        require_once('/docker/whp/web/libs/pdns-integration.php');
        
        $this->mysqlMgmt = new mysqlmgmt();
        $this->powerDNS = new PowerDNSIntegration($pdo);
    }
    
    /**
     * Set the import ID for tracking
     */
    public function setImportId($importId) {
        $this->importId = $importId;
    }
    
    /**
     * Main import function
     */
    public function importBackup($backupFilePath) {
        try {
            $this->logMessage("Starting cPanel backup import for user: {$this->username}");
            
            // Move to processing directory to avoid quota issues
            $processingDir = '/tmp/cpanel_processing_' . uniqid();
            mkdir($processingDir, 0700, true);
            
            $newBackupPath = $processingDir . '/' . basename($backupFilePath);
            if (!rename($backupFilePath, $newBackupPath)) {
                throw new Exception("Failed to move backup file to processing directory");
            }
            $this->backupPath = $newBackupPath;
            $this->logMessage("Moved backup file to temporary directory: " . $this->backupPath);
            
            // Validate backup file
            if (!$this->validateBackupFile()) {
                throw new Exception("Invalid backup file format");
            }
            
            // Extract backup
            if (!$this->extractBackup()) {
                throw new Exception("Failed to extract backup");
            }
            
            // Parse backup structure
            $backupData = $this->parseBackupStructure();
            if (!$backupData) {
                throw new Exception("Failed to parse backup structure");
            }
            
            // Import domains (creates domain records first)
            $domainsImported = $this->importDomains($backupData['domains']);
            
            // Create sites (uses existing WHP site creation)
            $sitesCreated = $this->createSites($backupData['domains']);
            
            // Import files
            $this->importFiles($backupData['domains']);
            
            // Import databases
            $this->importDatabases($backupData['databases']);
            
            // Import MySQL users  
            $this->importMySQLUsers($backupData['mysql_users']);
            
            // Create DNS records
            $this->createDNSRecords($backupData['domains']);
            
            // Cleanup
            $this->cleanup();
            
            return [
                'success' => true,
                'domains_imported' => count($domainsImported),
                'sites_created' => count($sitesCreated),
                'databases_imported' => count($backupData['databases']),
                'log' => $this->importLog
            ];
            
        } catch (Exception $e) {
            $this->logMessage("Import failed: " . $e->getMessage(), 'error');
            $this->cleanup();
            
            return [
                'success' => false,
                'error' => $e->getMessage(),
                'log' => $this->importLog
            ];
        }
    }
    
    /**
     * Create sites using WHP's existing site creation logic
     */
    private function createSites($domains) {
        $createdSites = [];
        
        // First ensure we have a default container type for cPanel imports
        $stmt = $this->pdo->prepare("SELECT id FROM whp.container_types WHERE name = 'PHP 8.2' AND active = 1 LIMIT 1");
        $stmt->execute();
        $containerType = $stmt->fetch();
        
        if (!$containerType) {
            // Use first active container type
            $stmt = $this->pdo->prepare("SELECT id FROM whp.container_types WHERE active = 1 LIMIT 1");
            $stmt->execute();
            $containerType = $stmt->fetch();
            
            if (!$containerType) {
                throw new Exception("No active container types available");
            }
        }
        
        $containerTypeId = $containerType['id'];
        
        // Create sites based on document root groupings
        foreach ($this->siteGroups as $docRoot => $siteGroup) {
            try {
                $primaryDomain = $siteGroup['primary_domain'];
                $additionalDomains = $siteGroup['additional_domains'];
                
                // Check if domain exists in WHP
                $stmt = $this->pdo->prepare("SELECT id, domain_name FROM whp.domains WHERE domain_name = ? AND username = ?");
                $stmt->execute([$primaryDomain, $this->username]);
                $domainRow = $stmt->fetch();
                
                if (!$domainRow) {
                    // Create domain first
                    $stmt = $this->pdo->prepare("
                        INSERT INTO whp.domains (domain_name, username, active, created_at) 
                        VALUES (?, ?, 1, NOW())
                    ");
                    $stmt->execute([$primaryDomain, $this->username]);
                    $domainId = $this->pdo->lastInsertId();
                } else {
                    $domainId = $domainRow['id'];
                }
                
                // Create site using WHP structure
                $siteName = $primaryDomain . " (Imported from cPanel)";
                
                // Create site directory
                $siteDir = '/docker/users/' . $this->username . '/' . $primaryDomain;
                if (!is_dir($siteDir)) {
                    mkdir($siteDir, 0755, true);
                    
                    // Set ownership
                    $uid = trim(shell_exec("id -u " . escapeshellarg($this->username)));
                    $gid = trim(shell_exec("id -g " . escapeshellarg($this->username)));
                    if (is_numeric($uid) && is_numeric($gid)) {
                        shell_exec("chown -R {$uid}:{$gid} " . escapeshellarg($siteDir));
                    }
                }
                
                // Insert site into database
                $stmt = $this->pdo->prepare("
                    INSERT INTO whp.sites (
                        site_name, 
                        primary_domain_id, 
                        username, 
                        container_type_id, 
                        container_count, 
                        cpu_per_container, 
                        memory_per_container, 
                        user_variables, 
                        auto_recreate_on_update,
                        created_at
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
                ");
                
                $stmt->execute([
                    $siteName,
                    $domainId,
                    $this->username,
                    $containerTypeId,
                    1, // container_count
                    0.25, // cpu_per_container
                    256, // memory_per_container
                    '{}', // user_variables
                    0 // auto_recreate_on_update
                ]);
                
                $siteId = $this->pdo->lastInsertId();
                
                // Insert into site_domains table
                $stmt = $this->pdo->prepare("
                    INSERT INTO whp.site_domains (site_id, domain_id, is_primary) 
                    VALUES (?, ?, 1)
                ");
                $stmt->execute([$siteId, $domainId]);
                
                // Add additional domains
                foreach ($additionalDomains as $additionalDomain) {
                    // Check if domain exists
                    $stmt = $this->pdo->prepare("SELECT id FROM whp.domains WHERE domain_name = ? AND username = ?");
                    $stmt->execute([$additionalDomain, $this->username]);
                    $addDomainRow = $stmt->fetch();
                    
                    if (!$addDomainRow) {
                        // Create domain
                        $stmt = $this->pdo->prepare("
                            INSERT INTO whp.domains (domain_name, username, active, created_at) 
                            VALUES (?, ?, 1, NOW())
                        ");
                        $stmt->execute([$additionalDomain, $this->username]);
                        $addDomainId = $this->pdo->lastInsertId();
                    } else {
                        $addDomainId = $addDomainRow['id'];
                    }
                    
                    // Add to site_domains
                    $stmt = $this->pdo->prepare("
                        INSERT INTO whp.site_domains (site_id, domain_id, is_primary) 
                        VALUES (?, ?, 0)
                    ");
                    $stmt->execute([$siteId, $addDomainId]);
                }
                
                // Also add to site_domains table (new structure for multiple domains per site)
                if ($this->tableExists('site_domains')) {
                    $stmt = $this->pdo->prepare("
                        INSERT INTO whp.site_domains (site_id, domain, domain_type) 
                        VALUES (?, ?, 'primary')
                        ON DUPLICATE KEY UPDATE domain = domain
                    ");
                    $stmt->execute([$siteId, $primaryDomain]);
                    
                    foreach ($additionalDomains as $additionalDomain) {
                        $stmt = $this->pdo->prepare("
                            INSERT INTO whp.site_domains (site_id, domain, domain_type) 
                            VALUES (?, ?, 'additional')
                            ON DUPLICATE KEY UPDATE domain = domain
                        ");
                        $stmt->execute([$siteId, $additionalDomain]);
                    }
                }
                
                $createdSites[] = [
                    'domain' => $primaryDomain,
                    'site_id' => $siteId,
                    'type' => 'primary',
                    'document_root' => $docRoot,
                    'additional_domains' => $additionalDomains
                ];
                
                $this->logMessage("Site created successfully for document root: " . $docRoot);
                
                // Track in cpanel_imported_domains
                $stmt = $this->pdo->prepare("
                    INSERT INTO whp.cpanel_imported_domains 
                    (import_id, domain, domain_type, original_path, whp_site_id, created_at) 
                    VALUES (?, ?, ?, ?, ?, NOW())
                ");
                $stmt->execute([$this->importId, $primaryDomain, 'primary', $docRoot, $siteId]);
                
                foreach ($additionalDomains as $additionalDomain) {
                    $stmt->execute([$this->importId, $additionalDomain, 'additional', $docRoot, $siteId]);
                }
                
            } catch (Exception $e) {
                $this->logMessage("Failed to create site for document root $docRoot: " . $e->getMessage(), 'error');
            }
        }
        
        return $createdSites;
    }
    
    /**
     * Import MySQL users using WHP's mysqlmgmt class
     */
    private function importMySQLUsers($mysqlUsers) {
        foreach ($mysqlUsers as $userGrant) {
            try {
                $originalUser = $userGrant['user'];
                $whpUser = $this->username . '_' . substr($originalUser, 0, 8);
                $password = $this->generatePassword();
                
                // Create user using WHP's method
                $result = $this->mysqlMgmt->createMySQLUser($whpUser, $password);
                
                if ($result['status'] === '0') {
                    $this->logMessage("MySQL user created: $originalUser -> $whpUser");
                    
                    // Track imported user
                    $stmt = $this->pdo->prepare("
                        INSERT INTO whp.cpanel_imported_mysql_users 
                        (import_id, original_username, whp_username, whp_password, created_at) 
                        VALUES (?, ?, ?, ?, NOW())
                    ");
                    $stmt->execute([$this->importId, $originalUser, $whpUser, $password]);
                    
                    // Grant privileges on imported databases
                    foreach ($userGrant['databases'] as $dbGrant) {
                        $whpDbName = $this->getWhpDatabaseName($dbGrant['database']);
                        if ($whpDbName) {
                            $this->mysqlMgmt->grantDatabasePrivileges($whpUser, $whpDbName, $dbGrant['privileges']);
                        }
                    }
                } else {
                    $this->logMessage("Failed to create MySQL user $originalUser: " . $result['msg'], 'error');
                }
                
            } catch (Exception $e) {
                $this->logMessage("Failed to create MySQL user {$userGrant['user']}: " . $e->getMessage(), 'error');
            }
        }
    }
    
    /**
     * Import databases using WHP's mysqlmgmt class
     */
    private function importDatabases($databases) {
        foreach ($databases as $database) {
            try {
                $originalDbName = $database['name'];
                $whpDbName = $this->username . '_' . preg_replace('/[^a-zA-Z0-9_]/', '', $originalDbName) . '_' . substr(uniqid(), 0, 8);
                
                // Create database using WHP's method
                $result = $this->mysqlMgmt->createDatabase($whpDbName, $this->username);
                
                if ($result['status'] === '0') {
                    $this->logMessage("Database created: $originalDbName -> $whpDbName");
                    
                    // Import the database dump
                    $dumpFile = $database['dump_file'];
                    if (file_exists($dumpFile)) {
                        $command = sprintf(
                            "mysql %s < %s 2>&1",
                            escapeshellarg($whpDbName),
                            escapeshellarg($dumpFile)
                        );
                        
                        $output = [];
                        $returnCode = 0;
                        exec($command, $output, $returnCode);
                        
                        if ($returnCode === 0) {
                            $this->logMessage("Database imported: $originalDbName -> $whpDbName");
                            
                            // Track imported database
                            $stmt = $this->pdo->prepare("
                                INSERT INTO whp.cpanel_imported_databases 
                                (import_id, original_db_name, whp_db_name, whp_db_user, whp_db_password, size_bytes, import_status, created_at) 
                                VALUES (?, ?, ?, ?, ?, ?, 'completed', NOW())
                            ");
                            $stmt->execute([
                                $this->importId, 
                                $originalDbName, 
                                $whpDbName,
                                '', // Will be set when users are created
                                '', // Will be set when users are created
                                filesize($dumpFile)
                            ]);
                        } else {
                            throw new Exception("Database import failed: " . implode("\n", $output));
                        }
                    }
                } else {
                    $this->logMessage("Failed to create database $originalDbName: " . $result['msg'], 'error');
                }
                
            } catch (Exception $e) {
                $this->logMessage("Failed to import database {$database['name']}: " . $e->getMessage(), 'error');
            }
        }
    }
    
    /**
     * Create DNS records using PowerDNS integration
     */
    private function createDNSRecords($domains) {
        foreach ($domains as $domain => $domainData) {
            try {
                // Check if domain zone exists
                $zoneExists = false;
                $zones = $this->powerDNS->getZones();
                foreach ($zones as $zone) {
                    if ($zone['name'] === $domain . '.') {
                        $zoneExists = true;
                        break;
                    }
                }
                
                if (!$zoneExists) {
                    // Create zone
                    $result = $this->powerDNS->createZone($domain, $this->username);
                    if ($result) {
                        $this->logMessage("DNS zone created for: $domain");
                    }
                }
                
                // Add A record pointing to server IP (you may want to configure this)
                $serverIP = $this->getServerIP();
                if ($serverIP) {
                    $this->powerDNS->addRecord($domain, $domain, 'A', $serverIP, 300);
                    $this->powerDNS->addRecord($domain, 'www.' . $domain, 'A', $serverIP, 300);
                    $this->logMessage("DNS A records created for: $domain");
                }
                
            } catch (Exception $e) {
                $this->logMessage("Failed to create DNS records for $domain: " . $e->getMessage(), 'warning');
            }
        }
    }
    
    /**
     * Helper function to get server IP
     */
    private function getServerIP() {
        // Try to get server's public IP
        $ip = trim(shell_exec("curl -s ifconfig.me 2>/dev/null || echo ''"));
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            return $ip;
        }
        
        // Fallback to primary network interface
        $ip = trim(shell_exec("ip -4 addr show scope global | grep inet | head -1 | awk '{print $2}' | cut -d/ -f1"));
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            return $ip;
        }
        
        return null;
    }
    
    /**
     * Check if table exists
     */
    private function tableExists($tableName) {
        $stmt = $this->pdo->prepare("
            SELECT COUNT(*) 
            FROM information_schema.TABLES 
            WHERE TABLE_SCHEMA = 'whp' 
            AND TABLE_NAME = ?
        ");
        $stmt->execute([$tableName]);
        return $stmt->fetchColumn() > 0;
    }
    
    /**
     * Get WHP database name from original name
     */
    private function getWhpDatabaseName($originalDbName) {
        $stmt = $this->pdo->prepare("
            SELECT whp_db_name 
            FROM whp.cpanel_imported_databases 
            WHERE import_id = ? 
            AND original_db_name = ?
        ");
        $stmt->execute([$this->importId, $originalDbName]);
        $row = $stmt->fetch();
        return $row ? $row['whp_db_name'] : null;
    }
    
    // ... (include other necessary methods from original class like validateBackupFile, extractBackup, etc.)
    
    private function logMessage($message, $level = 'info') {
        $timestamp = date('Y-m-d H:i:s');
        $this->importLog[] = "[$timestamp] [$level] $message";
        error_log("CpanelBackupImporter: [$timestamp] [$level] $message");
    }
    
    private function generatePassword($length = 16) {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()';
        return substr(str_shuffle($chars), 0, $length);
    }
}