#!/usr/bin/php
<?php

// 타임스탬프를 포함한 출력 함수
function logMessage($message) {
    $timestamp = date('Y-m-d H:i:s');
    echo "[$timestamp] $message";
}

// 인자 파싱 함수 (--key=value 형태만 허용)
function parseArguments($argv) {
    $args = [];
    for ($i = 1; $i < count($argv); $i++) {
        if ($argv[$i] === '--help') {
            $args['help'] = true;
        } elseif (preg_match('/^--([a-zA-Z]+)=(.*)$/', $argv[$i], $matches)) {
            $args[$matches[1]] = $matches[2];
        } else {
            logMessage("[WARNING] Invalid argument format: {$argv[$i]}\n");
            logMessage("          Use --key=value format (e.g., --host=localhost)\n\n");
        }
    }
    return $args;
}

$args = parseArguments($argv);

// --help 옵션 체크
if (isset($args['help'])) {
    echo "pty_mysql_backup_all_each_db_each_table version 2.0\n";
    echo "Copyright (C) 2019 by cpueblo, PlatyHouse Co.,LTD.\n";
    echo "Web site: https://www.platyhouse.com/\n\n";
    echo "Usage: php ./ptyMysqlBackup.php [OPTIONS]\n\n";
    echo "Options:\n";
    echo "  --host=<hostname>        MySQL host (default: localhost)\n";
    echo "  --username=<user>        MySQL username (default: root)\n";
    echo "  --password=<password>    MySQL password (optional if ~/.mysql_password exists)\n";
    echo "  --backupPath=<path>      Backup directory path (default: /root/pty_server_backup/mysql)\n";
    echo "  --help                   Show this help message\n\n";
    echo "Examples:\n";
    echo "  php ./ptyMysqlBackup.php --host=localhost --username=root --password=mypass\n";
    echo "  php ./ptyMysqlBackup.php --host=192.168.1.100 --username=admin\n";
    echo "  php ./ptyMysqlBackup.php --host=remotehost --backupPath=/backup/mysql\n\n";
    echo "Note:\n";
    echo "  - You can create ~/.mysql_password file with password (local or remote host)\n";
    echo "  - If password is not provided, script will try to read from ~/.mysql_password\n";
    echo "  - Each database backup will be compressed to .tgz format\n";
    exit(0);
}

$host = $args['host'] ?? null;
$user = $args['username'] ?? null;
$password = $args['password'] ?? null;
$backupPath = $args['backupPath'] ?? null;

if (!$host)    $host = "localhost";
if (!$user)    $user = "root";
if (!$backupPath)    $backupPath = "/root/pty_server_backup/mysql";

// 패스워드가 없으면 ~/.mysql_password 파일에서 읽기 시도
if (!$password)
{
    // 먼저 로컬 ~/.mysql_password 체크
    logMessage("[INFO] Checking local ~/.mysql_password file...\n");
    $passwordFile = getenv("HOME") . "/.mysql_password";
    if (file_exists($passwordFile)) {
        $password = trim(file_get_contents($passwordFile));
        logMessage("[INFO] Password loaded from local ~/.mysql_password\n");
    } else {
        logMessage("[INFO] Local ~/.mysql_password not found\n");
    }

    // 로컬에 없고 호스트가 localhost가 아니면 SSH로 원격 호스트에서 가져오기
    if (!$password && $host != "localhost" && $host != "127.0.0.1") {
        logMessage("[INFO] Trying to get password from remote host ($host)...\n");
        $sshCmd = "ssh root@$host 'cat ~/.mysql_password' 2>/dev/null";
        $remotePassword = trim(shell_exec($sshCmd));
        if ($remotePassword) {
            $password = $remotePassword;
            logMessage("[INFO] Password loaded from remote host = $password\n");
        } else {
            logMessage("[INFO] Remote ~/.mysql_password not found\n");
        }
    }
}

if (!$password)
{
    echo "[ERROR] Password is required!\n\n";
    echo "pty_mysql_backup_all_each_db_each_table version 2.0\n";
    echo "Copyright (C) 2019 by cpueblo, PlatyHouse Co.,LTD.\n";
    echo "Web site: https://www.platyhouse.com/\n\n";
    echo "Usage: php ./ptyMysqlBackup.php [OPTIONS]\n\n";
    echo "Options:\n";
    echo "  --host=<hostname>        MySQL host (default: localhost)\n";
    echo "  --username=<user>        MySQL username (default: root)\n";
    echo "  --password=<password>    MySQL password (optional if ~/.mysql_password exists)\n";
    echo "  --backupPath=<path>      Backup directory path (default: /root/pty_server_backup/mysql)\n";
    echo "  --help                   Show this help message\n\n";
    echo "Examples:\n";
    echo "  php ./ptyMysqlBackup.php --host=localhost --username=root --password=mypass\n";
    echo "  php ./ptyMysqlBackup.php --host=192.168.1.100 --username=admin\n";
    echo "  php ./ptyMysqlBackup.php --host=remotehost --backupPath=/backup/mysql\n\n";
    echo "Note:\n";
    echo "  - You can create ~/.mysql_password file with password (local or remote host)\n";
    echo "  - If password is not provided, script will try to read from ~/.mysql_password\n";
    echo "  - Each database backup will be compressed to .tgz format\n";
    exit(1);
}


// 백업 디렉토리 생성
if (!is_dir($backupPath)) {
    logMessage("[INFO] Creating backup directory: $backupPath\n");
    if (!mkdir($backupPath, 0755, true)) {
        logMessage("[ERROR] Failed to create backup directory: $backupPath\n");
        exit(1);
    }
}

logMessage("\n[INFO] Backup path: $backupPath\n");
logMessage("[INFO] Connecting to MySQL server: $host as $user, password = $password\n");


$connection = mysqli_connect($host, $user, $password);
if (!$connection) {
    logMessage('[ERROR] Could not connect database.' . mysqli_error()."\n");
    exit(1);
}
logMessage("[INFO] Connected successfully!\n\n");

logMessage("[INFO] Retrieving database list...\n");
$databases = mysqli_query($connection, "SHOW databases");
$dbCount = 0;
$totalTables = 0;
while ($databaseInfo = mysqli_fetch_array($databases)) { // go through each row that was returned in $result
    $dbName = $databaseInfo[0];

    # performance_schema, information_schema 는 백업 무시
    if ($dbName == "performance_schema" || $dbName == "information_schema") {
        logMessage("[SKIP] Skipping system database: $dbName\n");
        continue;
    }

    $dbCount++;
    logMessage("\n====================================\n");
    logMessage("[DB $dbCount] Processing database: $dbName\n");
    logMessage("====================================\n");

    $sql = "SHOW TABLES FROM `$dbName`";
    $result = mysqli_query($connection, $sql);

    if (!$result) {
        logMessage("[ERROR] DB Error, could not list tables\n");
        logMessage('[ERROR] MySQL Error: ' . mysqli_error($connection) . "\n");
        exit;
    }

    $tableCount = 0;
    $tables = [];
    while ($row = mysqli_fetch_row($result)) {
        $tables[] = $row[0];
    }

    $totalTablesInDb = count($tables);
    logMessage("[INFO] Found $totalTablesInDb tables in $dbName\n");

    foreach ($tables as $tableName) {
        $tableCount++;
        logMessage("[TABLE $tableCount/$totalTablesInDb] Backing up: $dbName.$tableName ... ");
        mysql_backup($host, $user, $password, $dbName, $tableName, $backupPath);
        logMessage("Done\n");
        $totalTables++;
    }

    // 데이터베이스 백업 완료 후 압축
    logMessage("[INFO] Compressing database backup...\n");
    $dbDir = $backupPath . "/" . $dbName;
    $tarFile = $backupPath . "/" . $dbName . ".tgz";

    // tar 명령 실행 (백업 경로로 이동해서 실행)
    $tarCmd = "cd \"$backupPath\" && tar czf \"$dbName.tgz\" \"$dbName\" 2>&1";
    exec($tarCmd, $tarOutput, $tarReturnCode);

    if ($tarReturnCode === 0) {
        logMessage("[INFO] Compressed to: $tarFile\n");

        // 압축 성공 시 원본 디렉토리 삭제
        logMessage("[INFO] Removing original directory...\n");
        $rmCmd = "rm -rf \"$dbDir\"";
        exec($rmCmd);
        logMessage("[INFO] Original directory removed\n");
    } else {
        logMessage("[ERROR] Failed to compress $dbName\n");
        logMessage(implode("\n", $tarOutput) . "\n");
    }
}

logMessage("\n====================================\n");
logMessage("[COMPLETE] Backup finished!\n");
logMessage("[STATS] Backup path: $backupPath\n");
logMessage("[STATS] Total databases: $dbCount\n");
logMessage("[STATS] Total tables: $totalTables\n");
logMessage("====================================\n");

function mysql_backup($host, $user, $password, $dbName, $tableName, $backupPath)
{
	if (strpos($dbName, "x_") === 0) {
        echo "(skipped: x_ prefix) ";
		return;
    }

    // 데이터베이스별 디렉토리 생성
    $dbDir = $backupPath . "/" . $dbName;
	if (!is_dir($dbDir)) {
        @mkdir($dbDir, 0755, true);
    }

    $outputFile = $dbDir . "/" . $tableName . ".sql";
    $cmd = "mysqldump -u $user -p$password -h $host $dbName $tableName --default-character-set=utf8mb4 --routines --events --add-drop-table --add-drop-database --complete-insert --extended-insert=TRUE --single-transaction --ssl-mode=DISABLED --max-allowed-packet=1G > \"$outputFile\" 2>&1";

    // 명령 실행 (출력 억제)
    exec($cmd, $output, $returnCode);

    if ($returnCode !== 0) {
        logMessage("\n[ERROR] Failed to backup $dbName.$tableName\n");
        logMessage(implode("\n", $output) . "\n");
    }
}

?>
