<?php

namespace App\Core;

use PDO;

/**
 * Migration Runner - تشغيل migrations بشكل منظم
 */
class MigrationRunner
{
    private PDO $db;
    private string $migrationsDir;
    private string $tableName = 'migrations_log';

    public function __construct(PDO $db, string $migrationsDir)
    {
        $this->db = $db;
        $this->migrationsDir = $migrationsDir;
        $this->ensureTableExists();
    }

    /**
     * التأكد من وجود جدول migrations_log
     */
    private function ensureTableExists(): void
    {
        try {
            $this->db->exec("
                CREATE TABLE IF NOT EXISTS {$this->tableName} (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    migration_file VARCHAR(255) NOT NULL UNIQUE,
                    executed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    execution_time FLOAT NULL,
                    status VARCHAR(20) NOT NULL DEFAULT 'success',
                    error_message TEXT NULL,
                    INDEX idx_migration_file (migration_file),
                    INDEX idx_executed_at (executed_at)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
            ");
        } catch (\Throwable $e) {
            // الجدول موجود بالفعل
        }
    }

    /**
     * التحقق من تشغيل migration
     */
    public function isMigrationRun(string $migrationFile): bool
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id FROM {$this->tableName} 
                WHERE migration_file = ? 
                AND status = 'success'
                LIMIT 1
            ");
            $stmt->execute([$migrationFile]);
            return $stmt->fetch() !== false;
        } catch (\Throwable $e) {
            return false;
        }
    }

    /**
     * تسجيل migration كمنفذ
     */
    public function markMigrationAsRun(string $migrationFile, float $executionTime = 0, ?string $error = null): void
    {
        try {
            $status = $error ? 'failed' : 'success';
            $stmt = $this->db->prepare("
                INSERT INTO {$this->tableName} 
                (migration_file, execution_time, status, error_message) 
                VALUES (?, ?, ?, ?)
                ON DUPLICATE KEY UPDATE 
                    executed_at = CURRENT_TIMESTAMP,
                    execution_time = VALUES(execution_time),
                    status = VALUES(status),
                    error_message = VALUES(error_message)
            ");
            $stmt->execute([$migrationFile, $executionTime, $status, $error]);
        } catch (\Throwable $e) {
            // تجاهل الأخطاء في التسجيل
        }
    }

    /**
     * تشغيل migration SQL
     */
    public function runSqlMigration(string $filePath): bool
    {
        if (!file_exists($filePath)) {
            return false;
        }

        $startTime = microtime(true);
        $content = file_get_contents($filePath);
        if ($content === false) {
            return false;
        }

        // تقسيم SQL statements
        $statements = array_filter(
            array_map('trim', explode(';', $content)),
            function($stmt) {
                return !empty($stmt) && strpos($stmt, '--') !== 0;
            }
        );

        try {
            $this->db->beginTransaction();
            
            foreach ($statements as $statement) {
                if (!empty($statement)) {
                    $this->db->exec($statement);
                }
            }
            
            $this->db->commit();
            $executionTime = microtime(true) - $startTime;
            
            $this->markMigrationAsRun(basename($filePath), $executionTime);
            return true;
        } catch (\Throwable $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            
            $executionTime = microtime(true) - $startTime;
            $this->markMigrationAsRun(basename($filePath), $executionTime, $e->getMessage());
            return false;
        }
    }

    /**
     * تشغيل migration PHP
     */
    public function runPhpMigration(string $filePath): bool
    {
        if (!file_exists($filePath)) {
            return false;
        }

        $startTime = microtime(true);
        
        try {
            $this->db->beginTransaction();
            
            // تشغيل ملف PHP
            require $filePath;
            
            $this->db->commit();
            $executionTime = microtime(true) - $startTime;
            
            $this->markMigrationAsRun(basename($filePath), $executionTime);
            return true;
        } catch (\Throwable $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            
            $executionTime = microtime(true) - $startTime;
            $this->markMigrationAsRun(basename($filePath), $executionTime, $e->getMessage());
            return false;
        }
    }

    /**
     * تشغيل جميع migrations المعلقة
     */
    public function runPendingMigrations(): array
    {
        $results = [
            'success' => [],
            'failed' => []
        ];

        if (!is_dir($this->migrationsDir)) {
            return $results;
        }

        // جلب جميع ملفات migrations
        $files = glob($this->migrationsDir . '/*.{sql,php}', GLOB_BRACE);
        usort($files, function($a, $b) {
            return strcmp(basename($a), basename($b));
        });

        foreach ($files as $file) {
            $fileName = basename($file);
            
            // تخطي migrations المنفذة
            if ($this->isMigrationRun($fileName)) {
                continue;
            }

            $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
            $success = false;

            if ($extension === 'sql') {
                $success = $this->runSqlMigration($file);
            } elseif ($extension === 'php') {
                $success = $this->runPhpMigration($file);
            }

            if ($success) {
                $results['success'][] = $fileName;
            } else {
                $results['failed'][] = $fileName;
            }
        }

        return $results;
    }

    /**
     * جلب قائمة migrations المنفذة
     */
    public function getExecutedMigrations(): array
    {
        try {
            $stmt = $this->db->query("
                SELECT migration_file, executed_at, execution_time, status 
                FROM {$this->tableName} 
                ORDER BY executed_at DESC
            ");
            return $stmt->fetchAll();
        } catch (\Throwable $e) {
            return [];
        }
    }
}
