<?php
class Initializer {
    private $indexerFilesDir;
    private $baseDir;
    public function __construct($indexerFilesDir, $baseDir = null) {
        $this->indexerFilesDir = $indexerFilesDir;
        $this->baseDir = $baseDir;
    }
    public function initializeCache($verbose = false) {
        if ($verbose) {
            echo "[Initializer] Setting up Cache system...\n";
        }
        $cacheDir = $this->indexerFilesDir . '/cache';
        $created = [];
        if (!is_dir($cacheDir)) {
            @mkdir($cacheDir, 0777, true);
            if (is_dir($cacheDir)) {
                @chmod($cacheDir, 0777);
                $created[] = $cacheDir;
                if ($verbose) echo "  [OK] Created: $cacheDir\n";
            }
        }
        $subdirs = ['files', 'img', 'zip'];
        foreach ($subdirs as $subdir) {
            $path = $cacheDir . '/' . $subdir;
            if (!is_dir($path)) {
                @mkdir($path, 0777, true);
                if (is_dir($path)) {
                    @chmod($path, 0777);
                    $created[] = $path;
                    if ($verbose) echo "  [OK] Created: $path\n";
                }
            }
        }
        $versionDb = $cacheDir . '/version.sqlite';
        if (!file_exists($versionDb)) {
            try {
                $pdo = new PDO('sqlite:' . $versionDb);
                $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $pdo->exec("CREATE TABLE IF NOT EXISTS version_info (
                    key TEXT PRIMARY KEY,
                    value TEXT NOT NULL,
                    cached_at INTEGER NOT NULL
                )");
                if (file_exists($versionDb)) {
                    @chmod($versionDb, 0666);
                }
                $created[] = $versionDb;
                if ($verbose) echo "  [OK] Created: $versionDb\n";
            } catch (Exception $e) {
                if ($verbose) echo "  [ERROR] Failed to create version.sqlite: " . $e->getMessage() . "\n";
            }
        }
        if ($verbose && empty($created)) {
            echo "  [INFO] Cache system already initialized\n";
        }
        return true;
    }
    public function initializeDatabase($verbose = false) {
        if ($verbose) {
            echo "[Initializer] Setting up Database system...\n";
        }
        $dbDir = $this->indexerFilesDir . '/db';
        $dbPath = $dbDir . '/indexer.sqlite';
        if (!is_dir($dbDir)) {
            @mkdir($dbDir, 0777, true);
            if (is_dir($dbDir)) {
                @chmod($dbDir, 0777);
                if ($verbose) echo "  [OK] Created: $dbDir\n";
            } else {
                if ($verbose) echo "  [ERROR] Failed to create: $dbDir\n";
                return false;
            }
        }
        try {
            $pdo = new PDO('sqlite:' . $dbPath);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            if (file_exists($dbPath)) {
                @chmod($dbPath, 0666);
            }
            if ($verbose) echo "  [OK] Database created: $dbPath\n";
            if ($verbose) echo "  [INFO] Creating database tables...\n";
            $pdo->exec("CREATE TABLE IF NOT EXISTS system_config (
                key TEXT PRIMARY KEY,
                value TEXT NOT NULL,
                last_updated INTEGER NOT NULL
            )");
            if ($verbose) echo "    [OK] system_config table\n";
            $pdo->exec("CREATE TABLE IF NOT EXISTS extension_mappings (
                extension TEXT PRIMARY KEY,
                indexing_setting TEXT,
                viewing_setting TEXT,
                last_updated INTEGER NOT NULL
            )");
            if ($verbose) echo "    [OK] extension_mappings table\n";
            $pdo->exec("CREATE TABLE IF NOT EXISTS icon_mappings (
                identifier TEXT PRIMARY KEY,
                icon_filename TEXT NOT NULL,
                last_updated INTEGER NOT NULL
            )");
            if ($verbose) echo "    [OK] icon_mappings table\n";
            $pdo->exec("CREATE TABLE IF NOT EXISTS file_metadata (
                path TEXT PRIMARY KEY,
                filename TEXT NOT NULL,
                extension TEXT,
                size INTEGER NOT NULL,
                modified INTEGER NOT NULL,
                is_directory INTEGER NOT NULL,
                parent_path TEXT,
                indexed_at INTEGER NOT NULL,
                last_verified INTEGER NOT NULL
            )");
            if ($verbose) echo "    [OK] file_metadata table\n";
            if ($verbose) echo "  [INFO] Creating indexes...\n";
            $pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_parent ON file_metadata(parent_path)");
            $pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_extension ON file_metadata(extension)");
            $pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_modified ON file_metadata(modified)");
            $pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_directory ON file_metadata(is_directory)");
            if ($verbose) echo "    [OK] Indexes created\n";
            if ($verbose) echo "  [INFO] Syncing system files to database...\n";
            $this->syncSystemFilesToDatabase($pdo, $verbose);
            if ($this->baseDir && is_dir($this->baseDir)) {
                if ($verbose) {
                    echo "  [INFO] Indexing existing files (this may take a while)...\n";
                }
                $this->indexExistingFiles($pdo, $verbose);
            }
            if ($verbose) echo "  [INFO] Optimizing database...\n";
            $pdo->exec("VACUUM");
            $pdo->exec("ANALYZE");
            if ($verbose) echo "    [OK] Database optimized\n";
        } catch (Exception $e) {
            if ($verbose) echo "  [ERROR] Database initialization failed: " . $e->getMessage() . "\n";
            return false;
        }
        if ($verbose) {
            echo "[Initializer] Database initialization complete!\n";
            $this->displayDatabaseStats($pdo);
        }
        return true;
    }
    private function syncSystemFilesToDatabase($pdo, $verbose = false) {
        $configFile = $this->indexerFilesDir . '/config.json';
        $extensionMapFile = $this->indexerFilesDir . '/local_api/extensionMap.json';
        $iconsFile = $this->indexerFilesDir . '/local_api/icons.json';
        $timestamp = time();
        if (file_exists($configFile)) {
            $configData = json_decode(file_get_contents($configFile), true);
            if ($configData) {
                $pdo->beginTransaction();
                try {
                    $stmt = $pdo->prepare("INSERT OR REPLACE INTO system_config (key, value, last_updated) VALUES (?, ?, ?)");
                    $stmt->execute(['config_data', json_encode($configData), $timestamp]);
                    $stmt->execute(['config_timestamp', $timestamp, $timestamp]);
                    if (isset($configData['version'])) {
                        $stmt->execute(['version', $configData['version'], $timestamp]);
                    }
                    if (isset($configData['main'])) {
                        foreach ($configData['main'] as $key => $value) {
                            $stmt->execute(['main_' . $key, json_encode($value), $timestamp]);
                        }
                    }
                    $pdo->commit();
                    if ($verbose) echo "    [OK] config.json synced\n";
                } catch (Exception $e) {
                    $pdo->rollBack();
                    if ($verbose) echo "    [ERROR] config.json sync failed: " . $e->getMessage() . "\n";
                }
            }
        } else {
            if ($verbose) echo "    [WARNING] config.json not found\n";
        }
        if (file_exists($extensionMapFile)) {
            $mapData = json_decode(file_get_contents($extensionMapFile), true);
            if ($mapData) {
                $pdo->beginTransaction();
                try {
                    $pdo->exec("DELETE FROM extension_mappings");
                    $stmt = $pdo->prepare("INSERT INTO extension_mappings (extension, indexing_setting, viewing_setting, last_updated) VALUES (?, ?, ?, ?)");
                    if (isset($mapData['indexing'])) {
                        foreach ($mapData['indexing'] as $ext => $setting) {
                            $viewingSetting = isset($mapData['viewing'][$ext]) ? $mapData['viewing'][$ext] : null;
                            $stmt->execute([$ext, $setting, $viewingSetting, $timestamp]);
                        }
                    }
                    if (isset($mapData['viewing'])) {
                        foreach ($mapData['viewing'] as $ext => $setting) {
                            if (!isset($mapData['indexing'][$ext])) {
                                $stmt->execute([$ext, null, $setting, $timestamp]);
                            }
                        }
                    }
                    $stmt = $pdo->prepare("INSERT OR REPLACE INTO system_config (key, value, last_updated) VALUES (?, ?, ?)");
                    $stmt->execute(['extension_map_timestamp', $timestamp, $timestamp]);
                    $pdo->commit();
                    if ($verbose) echo "    [OK] extensionMap.json synced\n";
                } catch (Exception $e) {
                    $pdo->rollBack();
                    if ($verbose) echo "    [ERROR] extensionMap.json sync failed: " . $e->getMessage() . "\n";
                }
            }
        } else {
            if ($verbose) echo "    [WARNING] extensionMap.json not found\n";
        }
        if (file_exists($iconsFile)) {
            $iconsData = json_decode(file_get_contents($iconsFile), true);
            if ($iconsData) {
                $pdo->beginTransaction();
                try {
                    $pdo->exec("DELETE FROM icon_mappings");
                    $stmt = $pdo->prepare("INSERT INTO icon_mappings (identifier, icon_filename, last_updated) VALUES (?, ?, ?)");
                    foreach ($iconsData as $identifier => $iconFile) {
                        $stmt->execute([$identifier, $iconFile, $timestamp]);
                    }
                    $stmt = $pdo->prepare("INSERT OR REPLACE INTO system_config (key, value, last_updated) VALUES (?, ?, ?)");
                    $stmt->execute(['icons_timestamp', $timestamp, $timestamp]);
                    $pdo->commit();
                    if ($verbose) echo "    [OK] icons.json synced\n";
                } catch (Exception $e) {
                    $pdo->rollBack();
                    if ($verbose) echo "    [ERROR] icons.json sync failed: " . $e->getMessage() . "\n";
                }
            }
        } else {
            if ($verbose) echo "    [WARNING] icons.json not found\n";
        }
    }
    private function indexExistingFiles($pdo, $verbose = false) {
        if (!$this->baseDir || !is_dir($this->baseDir)) {
            return;
        }
        $filesIndexed = 0;
        $dirsIndexed = 0;
        $this->indexDirectoryRecursive($pdo, $this->baseDir, '', $filesIndexed, $dirsIndexed, $verbose);
        if ($verbose) {
            echo "    [OK] Indexed {$filesIndexed} files and {$dirsIndexed} directories\n";
        }
    }
    private function indexDirectoryRecursive($pdo, $fullPath, $relativePath, &$filesCount, &$dirsCount, $verbose = false) {
        $items = @scandir($fullPath);
        if (!$items) return;
        $stmt = $pdo->prepare("INSERT OR REPLACE INTO file_metadata 
            (path, filename, extension, size, modified, is_directory, parent_path, indexed_at, last_verified) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
        $timestamp = time();
        foreach ($items as $item) {
            if ($item == '.' || $item == '..') continue;
            if ($item == '.indexer_files') continue;
            $itemPath = $fullPath . '/' . $item;
            $itemRelativePath = $relativePath ? $relativePath . '/' . $item : $item;
            if (is_dir($itemPath)) {
                $size = 0;
                $modified = filemtime($itemPath);
                $stmt->execute([
                    $itemRelativePath,
                    $item,
                    null,
                    $size,
                    $modified,
                    1,
                    $relativePath ?: null,
                    $timestamp,
                    $timestamp
                ]);
                $dirsCount++;
                $this->indexDirectoryRecursive($pdo, $itemPath, $itemRelativePath, $filesCount, $dirsCount, $verbose);
            } else {
                $extension = pathinfo($item, PATHINFO_EXTENSION);
                $size = filesize($itemPath);
                $modified = filemtime($itemPath);
                $stmt->execute([
                    $itemRelativePath,
                    $item,
                    $extension ? strtolower($extension) : null,
                    $size,
                    $modified,
                    0,
                    $relativePath ?: null,
                    $timestamp,
                    $timestamp
                ]);
                $filesCount++;
            }
            if ($verbose && ($filesCount + $dirsCount) % 500 == 0) {
                echo "      Progress: {$filesCount} files, {$dirsCount} directories\r";
            }
        }
    }
    private function displayDatabaseStats($pdo) {
        try {
            $stmt = $pdo->query("SELECT COUNT(*) as count FROM file_metadata WHERE is_directory = 0");
            $fileCount = $stmt->fetch(PDO::FETCH_ASSOC)['count'];
            $stmt = $pdo->query("SELECT COUNT(*) as count FROM file_metadata WHERE is_directory = 1");
            $dirCount = $stmt->fetch(PDO::FETCH_ASSOC)['count'];
            $stmt = $pdo->query("SELECT SUM(size) as total FROM file_metadata WHERE is_directory = 0");
            $totalSize = $stmt->fetch(PDO::FETCH_ASSOC)['total'] ?: 0;
            echo "\n[Statistics]\n";
            echo "  Files: " . number_format($fileCount) . "\n";
            echo "  Directories: " . number_format($dirCount) . "\n";
            echo "  Total Size: " . $this->formatBytes($totalSize) . "\n";
        } catch (Exception $e) {
        }
    }
    private function formatBytes($bytes) {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        return round($bytes, 2) . ' ' . $units[$i];
    }
}
if (php_sapi_name() === 'cli' && isset($argv)) {
    $scriptDir = dirname(dirname(dirname(__FILE__)));
    $indexerFilesDir = $scriptDir . '/.indexer_files';
    $baseDir = $scriptDir . '/files';
    $initializer = new Initializer($indexerFilesDir, $baseDir);
    $command = isset($argv[1]) ? $argv[1] : 'help';
    switch ($command) {
        case 'cache':
        case 'initializeCache':
            echo "Initializing Cache files...\n\n";
            $success = $initializer->initializeCache(true);
            echo "\n" . ($success ? "[SUCCESS] Cache initialized!" : "[FAILED] Cache initialization failed!") . "\n";
            break;
        case 'database':
        case 'initializeDatabase':
            echo "Initializing Database files...\n\n";
            $success = $initializer->initializeDatabase(true);
            echo "\n" . ($success ? "[SUCCESS] Database initialized!" : "[FAILED] Database initialization failed!") . "\n";
            break;
        case 'all':
        case 'both':
            echo "Initializing both Cache and Database files...\n\n";
            $cacheSuccess = $initializer->initializeCache(true);
            echo "\n";
            $dbSuccess = $initializer->initializeDatabase(true);
            echo "\n" . (($cacheSuccess && $dbSuccess) ? "[SUCCESS] All files initialized!" : "[WARNING] Some files failed to initialize!") . "\n";
            break;
        case 'help':
        default:
            echo "Commands:\n";
            echo "  cache      - Initialize Cache files only\n";
            echo "  database   - Initialize Database files only\n";
            echo "  all        - Initialize all files\n";
            break;
    }
    exit;
}
?>