#!/usr/bin/env php
<?php
/**
 * Backup System Manager - Control and monitor the decoupled backup system
 */

require_once(__DIR__ . '/../configs/config.php');
require_once('/docker/whp/web/libs/mysqlmgmt.php');
require_once(__DIR__ . '/../libs/BackupLocalStorage.php');

use WHPBackup\BackupLocalStorage;

// Parse command line arguments
$options = getopt("", ["status", "queue", "retry:", "cancel:", "workers", "cleanup", "storage", "help"]);

if (isset($options['help']) || empty($options)) {
    showHelp();
    exit(0);
}

try {
    $mysql = new mysqlmgmt();
    $db = $mysql->getMySQLConnection();
    $db->exec("USE whp");

    if (isset($options['status'])) {
        showSystemStatus($db);
    } elseif (isset($options['queue'])) {
        showUploadQueue($db);
    } elseif (isset($options['retry'])) {
        retryFailedUpload($db, $options['retry']);
    } elseif (isset($options['cancel'])) {
        cancelUpload($db, $options['cancel']);
    } elseif (isset($options['workers'])) {
        showWorkerStatus();
    } elseif (isset($options['cleanup'])) {
        runCleanup();
    } elseif (isset($options['storage'])) {
        showStorageStatus($db);
    }

} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
    exit(1);
}

function showHelp() {
    echo "Backup System Manager\n";
    echo "=====================\n\n";
    echo "Usage: php manage-backup-system.php [OPTIONS]\n\n";
    echo "Options:\n";
    echo "  --status            Show overall system status\n";
    echo "  --queue             Show upload queue status\n";
    echo "  --retry <id>        Retry a failed upload by queue ID\n";
    echo "  --cancel <id>       Cancel an upload by queue ID\n";
    echo "  --workers           Show worker process status\n";
    echo "  --cleanup           Run storage cleanup\n";
    echo "  --storage           Show local storage status\n";
    echo "  --help              Show this help message\n\n";
    echo "Examples:\n";
    echo "  php manage-backup-system.php --status\n";
    echo "  php manage-backup-system.php --queue\n";
    echo "  php manage-backup-system.php --retry 123\n";
}

function showSystemStatus($db) {
    echo "Backup System Status\n";
    echo str_repeat("=", 50) . "\n\n";

    // Backup creation status
    $stmt = $db->query("
        SELECT
            creation_status,
            COUNT(*) as count
        FROM backup_history
        WHERE DATE(started_at) = CURDATE()
        GROUP BY creation_status
    ");
    $creationStats = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

    echo "Today's Backup Creation:\n";
    foreach (['pending' => 'Pending', 'creating' => 'Creating', 'created' => 'Created', 'failed' => 'Failed'] as $status => $label) {
        $count = $creationStats[$status] ?? 0;
        echo "  $label: $count\n";
    }

    // Upload status
    $stmt = $db->query("
        SELECT
            upload_status,
            COUNT(*) as count
        FROM backup_history
        WHERE DATE(started_at) = CURDATE()
        GROUP BY upload_status
    ");
    $uploadStats = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

    echo "\nToday's Upload Status:\n";
    foreach (['pending' => 'Pending', 'uploading' => 'Uploading', 'uploaded' => 'Uploaded', 'failed' => 'Failed', 'skipped' => 'Skipped'] as $status => $label) {
        $count = $uploadStats[$status] ?? 0;
        echo "  $label: $count\n";
    }

    // Upload queue status
    $stmt = $db->query("
        SELECT
            status,
            COUNT(*) as count
        FROM backup_upload_queue
        GROUP BY status
    ");
    $queueStats = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

    echo "\nUpload Queue:\n";
    foreach (['queued' => 'Queued', 'processing' => 'Processing', 'completed' => 'Completed', 'failed' => 'Failed'] as $status => $label) {
        $count = $queueStats[$status] ?? 0;
        echo "  $label: $count\n";
    }

    // Storage info
    try {
        $localStorage = new BackupLocalStorage($db);
        $spaceInfo = $localStorage->getSpaceInfo();

        echo "\nLocal Storage:\n";
        echo "  Used: " . number_format($spaceInfo['current_size_gb'], 2) . " GB / " .
               $spaceInfo['max_size_gb'] . " GB (" .
               number_format($spaceInfo['usage_percentage'], 1) . "%)\n";
        echo "  Available: " . number_format($spaceInfo['available_gb'], 2) . " GB\n";
    } catch (Exception $e) {
        echo "\nLocal Storage: Error - " . $e->getMessage() . "\n";
    }
}

function showUploadQueue($db) {
    echo "Upload Queue Status\n";
    echo str_repeat("=", 80) . "\n";

    $stmt = $db->query("
        SELECT
            buq.id as queue_id,
            buq.backup_id,
            bh.backup_name,
            bh.user,
            buq.status,
            buq.priority,
            buq.retry_count,
            buq.worker_id,
            buq.created_at,
            buq.started_at,
            buq.next_retry_at,
            buq.error_message,
            bh.local_size
        FROM backup_upload_queue buq
        JOIN backup_history bh ON buq.backup_id = bh.id
        ORDER BY
            FIELD(buq.status, 'processing', 'queued', 'failed', 'completed'),
            buq.priority ASC,
            buq.created_at ASC
        LIMIT 50
    ");

    $uploads = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (empty($uploads)) {
        echo "No items in upload queue.\n";
        return;
    }

    printf("%-8s %-12s %-25s %-12s %-10s %-8s %-20s\n",
        "Queue ID", "Backup ID", "Name", "Status", "Size", "Retries", "Created");
    echo str_repeat("-", 80) . "\n";

    foreach ($uploads as $upload) {
        $size = $upload['local_size'] ? formatBytes($upload['local_size']) : 'Unknown';
        $name = strlen($upload['backup_name']) > 25 ?
            substr($upload['backup_name'], 0, 22) . '...' :
            $upload['backup_name'];

        printf("%-8s %-12s %-25s %-12s %-10s %-8s %-20s\n",
            $upload['queue_id'],
            $upload['backup_id'],
            $name,
            $upload['status'],
            $size,
            $upload['retry_count'],
            $upload['created_at']
        );

        if (!empty($upload['error_message'])) {
            echo "    Error: " . substr($upload['error_message'], 0, 60) . "...\n";
        }
        if ($upload['next_retry_at']) {
            echo "    Next retry: " . $upload['next_retry_at'] . "\n";
        }
    }
}

function retryFailedUpload($db, $queueId) {
    $stmt = $db->prepare("
        SELECT buq.*, bh.backup_name
        FROM backup_upload_queue buq
        JOIN backup_history bh ON buq.backup_id = bh.id
        WHERE buq.id = ?
    ");
    $stmt->execute([$queueId]);
    $upload = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$upload) {
        throw new Exception("Queue ID {$queueId} not found");
    }

    if ($upload['status'] !== 'failed') {
        echo "Upload is not in failed status (current: {$upload['status']})\n";
        return;
    }

    // Reset to queued status
    $stmt = $db->prepare("
        UPDATE backup_upload_queue
        SET status = 'queued', retry_count = 0, next_retry_at = NULL, error_message = NULL
        WHERE id = ?
    ");
    $stmt->execute([$queueId]);

    $stmt = $db->prepare("
        UPDATE backup_history
        SET upload_status = 'pending', upload_attempts = 0
        WHERE id = ?
    ");
    $stmt->execute([$upload['backup_id']]);

    echo "Upload {$queueId} ({$upload['backup_name']}) has been reset for retry\n";

    // Trigger upload worker
    $scriptPath = __DIR__ . '/backup-upload-worker.php';
    if (file_exists($scriptPath)) {
        echo "Starting upload worker...\n";
        exec("php " . escapeshellarg($scriptPath) . " > /dev/null 2>&1 &");
    }
}

function cancelUpload($db, $queueId) {
    $stmt = $db->prepare("
        SELECT buq.*, bh.backup_name
        FROM backup_upload_queue buq
        JOIN backup_history bh ON buq.backup_id = bh.id
        WHERE buq.id = ?
    ");
    $stmt->execute([$queueId]);
    $upload = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$upload) {
        throw new Exception("Queue ID {$queueId} not found");
    }

    if ($upload['status'] === 'completed') {
        echo "Upload is already completed\n";
        return;
    }

    // Cancel the upload
    $stmt = $db->prepare("
        UPDATE backup_upload_queue
        SET status = 'cancelled', completed_at = NOW()
        WHERE id = ?
    ");
    $stmt->execute([$queueId]);

    $stmt = $db->prepare("
        UPDATE backup_history
        SET upload_status = 'skipped'
        WHERE id = ?
    ");
    $stmt->execute([$upload['backup_id']]);

    echo "Upload {$queueId} ({$upload['backup_name']}) has been cancelled\n";
}

function showWorkerStatus() {
    echo "Worker Process Status\n";
    echo str_repeat("=", 50) . "\n";

    $workers = [
        'backup-worker' => '/tmp/backup-worker.lock',
        'upload-worker' => '/tmp/backup-upload-worker.lock'
    ];

    foreach ($workers as $name => $lockFile) {
        echo "$name: ";
        if (file_exists($lockFile)) {
            $pid = trim(file_get_contents($lockFile));
            if ($pid && posix_kill($pid, 0)) {
                echo "Running (PID: $pid)\n";
            } else {
                echo "Stale lock file (PID: $pid not running)\n";
            }
        } else {
            echo "Not running\n";
        }
    }
}

function runCleanup() {
    echo "Running backup cleanup...\n";
    $scriptPath = __DIR__ . '/backup-cleanup.php';
    if (file_exists($scriptPath)) {
        system("php " . escapeshellarg($scriptPath));
    } else {
        echo "Cleanup script not found: $scriptPath\n";
    }
}

function showStorageStatus($db) {
    try {
        $localStorage = new BackupLocalStorage($db);
        $spaceInfo = $localStorage->getSpaceInfo();

        echo "Local Storage Status\n";
        echo str_repeat("=", 40) . "\n";
        echo "Storage Path: /docker/backups/local\n";
        echo "Maximum Size: " . $spaceInfo['max_size_gb'] . " GB\n";
        echo "Current Usage: " . number_format($spaceInfo['current_size_gb'], 2) . " GB\n";
        echo "Available: " . number_format($spaceInfo['available_gb'], 2) . " GB\n";
        echo "Usage: " . number_format($spaceInfo['usage_percentage'], 1) . "%\n\n";

        // Show directory breakdown
        $basePath = '/docker/backups/local';
        $dirs = ['temp', 'ready', 'failed'];

        echo "Directory Breakdown:\n";
        foreach ($dirs as $dir) {
            $path = $basePath . '/' . $dir;
            if (is_dir($path)) {
                $size = getDirSize($path);
                $count = count(glob($path . '/*'));
                echo "  $dir: " . formatBytes($size) . " ($count files)\n";
            }
        }

    } catch (Exception $e) {
        echo "Error getting storage status: " . $e->getMessage() . "\n";
    }
}

function getDirSize($dir) {
    $size = 0;
    if (is_dir($dir)) {
        $files = glob($dir . '/*');
        foreach ($files as $file) {
            if (is_file($file)) {
                $size += filesize($file);
            }
        }
    }
    return $size;
}

function formatBytes($bytes) {
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);
    $bytes /= (1 << (10 * $pow));
    return number_format($bytes, 2) . ' ' . $units[$pow];
}