<?php
/**
 * ===================================================
 * نظام الترحيل التلقائي - Auto Migration System
 * ===================================================
 * 
 * الغرض: نقل البيانات من supehgku_Packagemaker إلى supehgku_test0
 * النوع: Idempotent (يمكن إعادة التشغيل بأمان)
 * الكاتب: Migration Architect
 * التاريخ: 2025-10-25
 */

// ====== الإعدادات ======
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('max_execution_time', 3600); // ساعة واحدة
ini_set('memory_limit', '512M');

// المسارات
define('ROOT_DIR', dirname(__DIR__));
define('CONFIG_FILE', ROOT_DIR . '/config/migration_config.ini');
define('LOG_DIR', ROOT_DIR . '/logs');
define('BACKUP_DIR', ROOT_DIR . '/backups');

// ====== الفئات المساعدة ======

class Logger {
    private $logFile;
    private $handle;
    
    public function __construct($logFile) {
        $this->logFile = $logFile;
        $this->handle = fopen($logFile, 'a');
        if (!$this->handle) {
            die("فشل فتح ملف السجل: $logFile\n");
        }
    }
    
    public function log($level, $message) {
        $timestamp = date('Y-m-d H:i:s');
        $line = "[$timestamp] $level: $message\n";
        fwrite($this->handle, $line);
        echo $line; // طباعة أيضاً
    }
    
    public function info($msg) { $this->log('INFO', $msg); }
    public function success($msg) { $this->log('SUCCESS', $msg); }
    public function warning($msg) { $this->log('WARNING', $msg); }
    public function error($msg) { $this->log('ERROR', $msg); }
    public function critical($msg) { $this->log('CRITICAL', $msg); }
    
    public function __destruct() {
        if ($this->handle) {
            fclose($this->handle);
        }
    }
}

class MigrationStats {
    public $tablesProcessed = 0;
    public $recordsMigrated = 0;
    public $recordsSkipped = 0;
    public $errors = 0;
    public $startTime;
    public $endTime;
    
    public function __construct() {
        $this->startTime = microtime(true);
    }
    
    public function finish() {
        $this->endTime = microtime(true);
    }
    
    public function getDuration() {
        return round($this->endTime - $this->startTime, 2);
    }
    
    public function getReport() {
        return [
            'tables_processed' => $this->tablesProcessed,
            'records_migrated' => $this->recordsMigrated,
            'records_skipped' => $this->recordsSkipped,
            'errors' => $this->errors,
            'duration' => $this->getDuration() . ' ثانية'
        ];
    }
}

// ====== الفئة الرئيسية ======

class AutoMigration {
    private $sourceDB;
    private $targetDB;
    private $config;
    private $logger;
    private $stats;
    private $dryRun;
    
    public function __construct($configFile) {
        // قراءة الإعدادات
        if (!file_exists($configFile)) {
            die("ملف الإعدادات غير موجود: $configFile\n");
        }
        
        $this->config = parse_ini_file($configFile, true);
        $this->dryRun = $this->config['migration_settings']['dry_run'] ?? false;
        
        // إنشاء السجل
        $logFile = LOG_DIR . '/migration_' . date('Ymd_His') . '.log';
        $this->logger = new Logger($logFile);
        $this->stats = new MigrationStats();
        
        $this->logger->info("==================================================");
        $this->logger->info("بدء نظام الترحيل التلقائي");
        $this->logger->info("الوضع: " . ($this->dryRun ? 'اختبار (Dry Run)' : 'تنفيذ حقيقي'));
        $this->logger->info("==================================================");
        
        // الاتصال بالقواعد
        $this->connectDatabases();
    }
    
    private function connectDatabases() {
        try {
            // قاعدة المصدر (القديمة)
            $src = $this->config['source_database'];
            $this->sourceDB = new PDO(
                "mysql:host={$src['host']};port={$src['port']};dbname={$src['database']};charset={$src['charset']}",
                $src['username'],
                $src['password'],
                [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
            );
            $this->logger->success("اتصال ناجح بقاعدة المصدر: {$src['database']}");
            
            // قاعدة الهدف (الجديدة)
            $tgt = $this->config['target_database'];
            $this->targetDB = new PDO(
                "mysql:host={$tgt['host']};port={$tgt['port']};dbname={$tgt['database']};charset={$tgt['charset']}",
                $tgt['username'],
                $tgt['password'],
                [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
            );
            $this->logger->success("اتصال ناجح بقاعدة الهدف: {$tgt['database']}");
            
        } catch (PDOException $e) {
            $this->logger->critical("فشل الاتصال بقاعدة البيانات: " . $e->getMessage());
            die();
        }
    }
    
    public function run() {
        try {
            // المرحلة 0: التحضير
            $this->phase0_preparation();
            
            // المرحلة 1: البيانات الأساسية
            $this->phase1_coreData();
            
            // المرحلة 2: الربط
            $this->phase2_linking();
            
            // المرحلة 3: البيانات الاختيارية
            $this->phase3_optionalData();
            
            // المرحلة 4: التنظيف والتحقق
            $this->phase4_cleanup();
            
            // النتيجة النهائية
            $this->stats->finish();
            $this->printFinalReport();
            
        } catch (Exception $e) {
            $this->logger->critical("خطأ حرج: " . $e->getMessage());
            $this->logger->error("تتبع الخطأ: " . $e->getTraceAsString());
            
            if ($this->config['migration_settings']['stop_on_error']) {
                die("\n❌ توقف الترحيل بسبب خطأ.\n");
            }
        }
    }
    
    // ====== المرحلة 0: التحضير ======
    private function phase0_preparation() {
        $this->logger->info("");
        $this->logger->info("=== المرحلة 0: التحضير ===");
        
        // التحقق من المجموعة الافتراضية
        $stmt = $this->targetDB->query("SELECT id FROM account_groups WHERE id = 1");
        if (!$stmt->fetch()) {
            $this->logger->error("المجموعة الافتراضية (id=1) غير موجودة!");
            $this->logger->info("إنشاء المجموعة الافتراضية...");
            
            if (!$this->dryRun) {
                $this->targetDB->exec("
                    INSERT INTO account_groups (id, group_name, description, is_default, locked) 
                    VALUES (1, 'default', 'المجموعة العامة - تحتوي جميع الحسابات', 1, 1)
                ");
            }
            $this->logger->success("تم إنشاء المجموعة الافتراضية");
        } else {
            $this->logger->success("المجموعة الافتراضية (id=1) موجودة");
        }
        
        // نسخة احتياطية
        if ($this->config['migration_settings']['backup_before_migration'] && !$this->dryRun) {
            $this->createBackup();
        }
        
        // تعطيل Foreign Keys مؤقتاً
        if (!$this->dryRun) {
            $this->targetDB->exec("SET FOREIGN_KEY_CHECKS=0");
            $this->logger->info("تم تعطيل Foreign Keys مؤقتاً");
        }
    }
    
    private function createBackup() {
        $this->logger->info("إنشاء نسخة احتياطية...");
        
        $backupFile = BACKUP_DIR . '/backup_' . date('Ymd_His') . '.sql';
        $tgt = $this->config['target_database'];
        
        $cmd = sprintf(
            'mysqldump -h%s -P%s -u%s %s %s > %s',
            escapeshellarg($tgt['host']),
            escapeshellarg($tgt['port']),
            escapeshellarg($tgt['username']),
            $tgt['password'] ? '-p' . escapeshellarg($tgt['password']) : '',
            escapeshellarg($tgt['database']),
            escapeshellarg($backupFile)
        );
        
        exec($cmd, $output, $returnCode);
        
        if ($returnCode === 0 && file_exists($backupFile)) {
            $size = round(filesize($backupFile) / 1024 / 1024, 2);
            $this->logger->success("تم إنشاء نسخة احتياطية: $backupFile ($size MB)");
        } else {
            $this->logger->warning("فشل إنشاء النسخة الاحتياطية");
        }
    }
    
    // ====== المرحلة 1: البيانات الأساسية ======
    private function phase1_coreData() {
        $this->logger->info("");
        $this->logger->info("=== المرحلة 1: البيانات الأساسية ===");
        
        $tables = $this->config['tables_to_migrate'];
        
        // 1.1 sub_bots
        if ($tables['sub_bots'] ?? false) {
            $this->migrateTable('sub_bots', 
                ['id', 'label', 'bot_token', 'channel_id', 'max_users', 'current_users', 'paused', 'welcome_message', 'created_at']
            );
        }
        
        // 1.2 steam_accounts
        if ($tables['steam_accounts'] ?? false) {
            $this->migrateTable('steam_accounts', 
                ['id', 'account_name', 'shared_secret', 'active', 'created_at']
            );
        }
        
        // 1.3 allowed_users
        if ($tables['allowed_users'] ?? false) {
            $this->migrateTable('allowed_users', 
                ['id', 'bot_token', 'user_id', 'banned', 'created_at']
            );
        }
        
        // 1.4 message_templates
        if ($tables['message_templates'] ?? false) {
            $this->migrateMessageTemplates();
        }
    }
    
    private function migrateTable($tableName, $columns) {
        $this->logger->info("ترحيل جدول: $tableName");
        
        try {
            // عدد السجلات في المصدر
            $count = $this->sourceDB->query("SELECT COUNT(*) FROM $tableName")->fetchColumn();
            $this->logger->info("عدد السجلات في المصدر: $count");
            
            if ($count == 0) {
                $this->logger->warning("الجدول فارغ في المصدر");
                return;
            }
            
            if ($this->dryRun) {
                $this->logger->info("[DRY RUN] سيتم نقل $count سجل");
                $this->stats->recordsMigrated += $count;
                $this->stats->tablesProcessed++;
                return;
            }
            
            // الاستعلام
            $cols = implode(', ', $columns);
            $placeholders = implode(', ', array_fill(0, count($columns), '?'));
            
            $selectSQL = "SELECT $cols FROM $tableName";
            $insertSQL = "INSERT IGNORE INTO $tableName ($cols) VALUES ($placeholders)";
            
            $stmt = $this->sourceDB->query($selectSQL);
            $insertStmt = $this->targetDB->prepare($insertSQL);
            
            $migrated = 0;
            $skipped = 0;
            
            while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
                try {
                    $insertStmt->execute($row);
                    if ($insertStmt->rowCount() > 0) {
                        $migrated++;
                    } else {
                        $skipped++;
                    }
                } catch (PDOException $e) {
                    $this->logger->warning("تخطي سجل: " . $e->getMessage());
                    $skipped++;
                }
            }
            
            $this->stats->recordsMigrated += $migrated;
            $this->stats->recordsSkipped += $skipped;
            $this->stats->tablesProcessed++;
            
            $this->logger->success("✅ $tableName: $migrated منقول، $skipped متخطى");
            
        } catch (Exception $e) {
            $this->stats->errors++;
            $this->logger->error("خطأ في $tableName: " . $e->getMessage());
        }
    }
    
    private function migrateMessageTemplates() {
        $this->logger->info("ترحيل قوالب الرسائل (مع دمج)");
        
        try {
            $count = $this->sourceDB->query("SELECT COUNT(*) FROM message_templates")->fetchColumn();
            $this->logger->info("عدد القوالب في المصدر: $count");
            
            if ($this->dryRun) {
                $this->logger->info("[DRY RUN] سيتم دمج $count قالب");
                return;
            }
            
            $stmt = $this->sourceDB->query("SELECT `key`, text FROM message_templates");
            $insertSQL = "INSERT INTO message_templates (`key`, text) VALUES (?, ?) ON DUPLICATE KEY UPDATE text = VALUES(text)";
            $insertStmt = $this->targetDB->prepare($insertSQL);
            
            $merged = 0;
            while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
                $insertStmt->execute($row);
                $merged++;
            }
            
            $this->stats->recordsMigrated += $merged;
            $this->logger->success("✅ message_templates: $merged قالب مدمج");
            
        } catch (Exception $e) {
            $this->stats->errors++;
            $this->logger->error("خطأ في message_templates: " . $e->getMessage());
        }
    }
    
    // ====== المرحلة 2: الربط ======
    private function phase2_linking() {
        $this->logger->info("");
        $this->logger->info("=== المرحلة 2: ربط العلاقات ===");
        
        // 2.1 ربط الحسابات بالمجموعة الافتراضية
        $this->linkAccountsToDefaultGroup();
        
        // 2.2 ربط البوتات بالمجموعة الافتراضية
        $this->linkBotsToDefaultGroup();
    }
    
    private function linkAccountsToDefaultGroup() {
        $this->logger->info("ربط الحسابات بالمجموعة الافتراضية (id=1)");
        
        try {
            if ($this->dryRun) {
                $count = $this->targetDB->query("SELECT COUNT(*) FROM steam_accounts")->fetchColumn();
                $this->logger->info("[DRY RUN] سيتم ربط $count حساب");
                return;
            }
            
            $sql = "INSERT IGNORE INTO group_accounts (group_id, account_id) 
                    SELECT 1, id FROM steam_accounts";
            
            $this->targetDB->exec($sql);
            $linked = $this->targetDB->query("SELECT COUNT(*) FROM group_accounts WHERE group_id = 1")->fetchColumn();
            
            $this->logger->success("✅ تم ربط $linked حساب بالمجموعة الافتراضية");
            
        } catch (Exception $e) {
            $this->stats->errors++;
            $this->logger->error("خطأ في ربط الحسابات: " . $e->getMessage());
        }
    }
    
    private function linkBotsToDefaultGroup() {
        $this->logger->info("ربط البوتات بالمجموعة الافتراضية (id=1)");
        
        try {
            if ($this->dryRun) {
                $count = $this->targetDB->query("SELECT COUNT(*) FROM sub_bots")->fetchColumn();
                $this->logger->info("[DRY RUN] سيتم ربط $count بوت");
                return;
            }
            
            $sql = "INSERT IGNORE INTO bot_groups (bot_id, group_id) 
                    SELECT id, 1 FROM sub_bots";
            
            $this->targetDB->exec($sql);
            $linked = $this->targetDB->query("SELECT COUNT(*) FROM bot_groups WHERE group_id = 1")->fetchColumn();
            
            $this->logger->success("✅ تم ربط $linked بوت بالمجموعة الافتراضية");
            
        } catch (Exception $e) {
            $this->stats->errors++;
            $this->logger->error("خطأ في ربط البوتات: " . $e->getMessage());
        }
    }
    
    // ====== المرحلة 3: البيانات الاختيارية ======
    private function phase3_optionalData() {
        $this->logger->info("");
        $this->logger->info("=== المرحلة 3: البيانات الاختيارية ===");
        
        $tables = $this->config['tables_to_migrate'];
        
        // steam_requests (إن كان مفعلاً)
        if ($tables['steam_requests'] ?? false) {
            $this->migrateSteamRequests();
        } else {
            $this->logger->info("تم تخطي steam_requests (معطل في الإعدادات)");
        }
    }
    
    private function migrateSteamRequests() {
        $this->logger->info("ترحيل سجل الطلبات (بالدفعات)");
        
        try {
            $count = $this->sourceDB->query("SELECT COUNT(*) FROM steam_requests")->fetchColumn();
            $this->logger->info("عدد الطلبات: $count");
            
            if ($count == 0) {
                $this->logger->warning("لا توجد طلبات");
                return;
            }
            
            if ($this->dryRun) {
                $this->logger->info("[DRY RUN] سيتم نقل $count طلب");
                return;
            }
            
            $batchSize = $this->config['migration_settings']['batch_size'] ?? 1000;
            $offset = 0;
            $migrated = 0;
            
            while ($offset < $count) {
                $sql = "INSERT IGNORE INTO steam_requests SELECT * FROM " .
                       $this->config['source_database']['database'] . ".steam_requests LIMIT $offset, $batchSize";
                
                $this->targetDB->exec($sql);
                $migrated += $this->targetDB->query("SELECT ROW_COUNT()")->fetchColumn();
                $offset += $batchSize;
                
                $this->logger->info("دفعة: $offset / $count");
            }
            
            $this->stats->recordsMigrated += $migrated;
            $this->logger->success("✅ steam_requests: $migrated طلب");
            
        } catch (Exception $e) {
            $this->stats->errors++;
            $this->logger->error("خطأ في steam_requests: " . $e->getMessage());
        }
    }
    
    // ====== المرحلة 4: التنظيف والتحقق ======
    private function phase4_cleanup() {
        $this->logger->info("");
        $this->logger->info("=== المرحلة 4: التنظيف والتحقق ===");
        
        if ($this->dryRun) {
            $this->logger->info("[DRY RUN] تخطي التنظيف");
            return;
        }
        
        // إعادة تفعيل Foreign Keys
        $this->targetDB->exec("SET FOREIGN_KEY_CHECKS=1");
        $this->logger->success("تم إعادة تفعيل Foreign Keys");
        
        // تحديث Auto Increment
        $this->updateAutoIncrements();
        
        // التحقق
        if ($this->config['migration_settings']['verify_after_migration']) {
            $this->verify();
        }
    }
    
    private function updateAutoIncrements() {
        $this->logger->info("تحديث Auto Increment Counters");
        
        $tables = ['sub_bots', 'steam_accounts', 'allowed_users'];
        
        foreach ($tables as $table) {
            try {
                $max = $this->targetDB->query("SELECT MAX(id) FROM $table")->fetchColumn();
                if ($max) {
                    $this->targetDB->exec("ALTER TABLE $table AUTO_INCREMENT = " . ($max + 1));
                    $this->logger->info("$table: AUTO_INCREMENT = " . ($max + 1));
                }
            } catch (Exception $e) {
                $this->logger->warning("تخطي $table: " . $e->getMessage());
            }
        }
    }
    
    private function verify() {
        $this->logger->info("التحقق من سلامة البيانات");
        
        // التحقق من الحسابات اليتيمة
        $orphaned = $this->targetDB->query("
            SELECT COUNT(*) FROM steam_accounts sa
            LEFT JOIN group_accounts ga ON ga.account_id = sa.id
            WHERE ga.account_id IS NULL
        ")->fetchColumn();
        
        if ($orphaned > 0) {
            $this->logger->warning("حسابات يتيمة (بدون مجموعة): $orphaned");
        } else {
            $this->logger->success("جميع الحسابات مربوطة بمجموعة ✅");
        }
        
        // التحقق من البوتات اليتيمة
        $orphaned = $this->targetDB->query("
            SELECT COUNT(*) FROM sub_bots sb
            LEFT JOIN bot_groups bg ON bg.bot_id = sb.id
            WHERE bg.bot_id IS NULL
        ")->fetchColumn();
        
        if ($orphaned > 0) {
            $this->logger->warning("بوتات يتيمة (بدون مجموعة): $orphaned");
        } else {
            $this->logger->success("جميع البوتات مربوطة بمجموعة ✅");
        }
    }
    
    // ====== التقرير النهائي ======
    private function printFinalReport() {
        $this->logger->info("");
        $this->logger->info("==================================================");
        $this->logger->info("التقرير النهائي");
        $this->logger->info("==================================================");
        
        $report = $this->stats->getReport();
        
        foreach ($report as $key => $value) {
            $this->logger->info(ucfirst(str_replace('_', ' ', $key)) . ": $value");
        }
        
        if ($this->stats->errors == 0) {
            $this->logger->success("");
            $this->logger->success("🎉 اكتمل الترحيل بنجاح!");
            $this->logger->success("");
        } else {
            $this->logger->warning("");
            $this->logger->warning("⚠️ اكتمل مع " . $this->stats->errors . " خطأ");
            $this->logger->warning("");
        }
    }
}

// ====== التشغيل ======

// التحقق من المجلدات
if (!is_dir(LOG_DIR)) mkdir(LOG_DIR, 0755, true);
if (!is_dir(BACKUP_DIR)) mkdir(BACKUP_DIR, 0755, true);

// تشغيل الترحيل
$migration = new AutoMigration(CONFIG_FILE);
$migration->run();
