<?php
require_once dirname(__DIR__) . '/config/config.php';
require_once dirname(__DIR__) . '/includes/db.php';
require_once dirname(__DIR__) . '/includes/functions.php';
require_once dirname(__DIR__) . '/includes/functions_backup.php';
require_once dirname(__DIR__) . '/includes/auth.php';
require_once dirname(__DIR__) . '/includes/admin_jobs.php';
requirePermission('backup_restore');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: backup_center.php');
    exit;
}
requireCsrfToken();

$adminJobId = null;

function createRestoreSafetyBackupV2() {
    $backup = createJsonBackup('full_db', null, 'Automatic safety backup before restore', true);
    $source = backupFilePath($backup['file_name']);
    $safetyName = preg_replace('/\.json$/', '_before_restore.json', $backup['file_name']);
    $target = ensureBackupStorage() . '/' . $safetyName;
    if ($source && is_file($source) && rename($source, $target)) {
        return $safetyName;
    }
    return $backup['file_name'];
}

try {
    $file = backupSafeFilename($_POST['backup_file'] ?? '');
    if ($file === '') throw new RuntimeException('잘못된 백업 파일명입니다.');
    if (trim((string)($_POST['confirm_phrase'] ?? '')) !== '복원합니다') throw new RuntimeException('확인 문구가 일치하지 않습니다.');
    $path = backupFilePath($file);
    if (!$path || !is_file($path)) throw new RuntimeException('백업 폴더 내부의 파일만 복원할 수 있습니다.');

    $jobStart = startAdminJob('restore', '전체 DB 복원', 'restore:full', ['file_name' => $file], true);
    if (empty($jobStart['ok']) && !empty($jobStart['duplicate'])) {
        header('Location: backup_center.php?status=error&message=' . urlencode('이미 복원 작업이 진행 중입니다. 작업 큐에서 진행 상태를 확인하세요.'));
        exit;
    }
    $adminJobId = (int)($jobStart['id'] ?? 0);

    $data = readBackupJson($path);
    $inspection = inspectBackupData($data);
    if (!$inspection['valid']) throw new RuntimeException(implode(' ', $inspection['errors']));
    $exportType = (string)($data['export_type'] ?? $data['type'] ?? '');
    if (!in_array($exportType, ['full_db', 'melonlite_json_backup'], true)) {
        throw new RuntimeException('전체 DB 백업 파일만 전체 복원에 사용할 수 있습니다.');
    }

    logMaintenance('restore_started', 'Restore started: ' . $file);
    writeAuditLog('restore_started', 'Restore started: ' . $file, 'started', 'warning', 'backup', $file);
    if (function_exists('writeAppLog')) writeAppLog('warning', 'restore', 'Full restore started', ['file_name' => $file]);
    $safety = createRestoreSafetyBackupV2();

    $tablesData = backupDataTables($data);
    $pdo = getDBConnection();
    $pdo->beginTransaction();
    $pdo->exec('SET FOREIGN_KEY_CHECKS=0');
    foreach (backupChildFirstTables() as $table) {
        if (!array_key_exists($table, $tablesData) || !backupTableExists($table)) continue;
        $pdo->exec("DELETE FROM `$table`");
    }

    $insertOrder = array_reverse(backupChildFirstTables());
    foreach ($insertOrder as $table) {
        if (!array_key_exists($table, $tablesData) || !is_array($tablesData[$table]) || !backupTableExists($table)) continue;
        $tableColumns = backupTableColumns($table);
        foreach ($tablesData[$table] as $row) {
            if (!is_array($row) || empty($row)) continue;
            $cols = array_values(array_intersect(array_keys($row), $tableColumns));
            $cols = array_values(array_filter($cols, function ($col) {
                return preg_match('/^[A-Za-z0-9_]+$/', $col);
            }));
            if (empty($cols)) continue;
            $colSql = '`' . implode('`,`', $cols) . '`';
            $placeholders = [];
            $params = [];
            foreach ($cols as $index => $col) {
                $placeholder = ':v' . $index;
                $placeholders[] = $placeholder;
                $params[$placeholder] = $row[$col];
            }
            $stmt = $pdo->prepare("INSERT INTO `$table` ($colSql) VALUES (" . implode(',', $placeholders) . ")");
            $stmt->execute($params);
        }
    }
    $pdo->exec('SET FOREIGN_KEY_CHECKS=1');
    $pdo->commit();

    finishAdminJob($adminJobId, 'completed', [
        'processed_count' => count($tablesData),
        'summary_message' => '전체 DB 복원이 완료되었습니다.',
        'context' => [
            'file_name' => $file,
            'safety_backup' => $safety,
            'table_count' => count($tablesData),
        ],
    ]);
    logMaintenance('restore_completed', 'Restore completed: ' . $file . ' / safety backup: ' . $safety);
    writeAuditLog('restore_completed', 'Restore completed: ' . $file . ' / safety backup: ' . $safety, 'success', 'warning', 'backup', $file);
    if (function_exists('writeAppLog')) writeAppLog('warning', 'restore', 'Full restore completed', ['file_name' => $file, 'safety_backup' => $safety]);
    header('Location: backup_center.php?status=success&message=' . urlencode('복원을 완료했습니다. 안전 백업: ' . $safety));
} catch (Throwable $e) {
    if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) $pdo->rollBack();
    try { if (isset($pdo) && $pdo instanceof PDO) $pdo->exec('SET FOREIGN_KEY_CHECKS=1'); } catch (Throwable $ignored) {}
    $safeMessage = maskInternalPathText($e->getMessage());
    finishAdminJob($adminJobId, 'failed', [
        'processed_count' => 0,
        'failed_count' => 1,
        'summary_message' => '복원 작업이 실패했습니다.',
        'error_type' => 'restore_error',
        'context' => ['file_name' => $file ?? '', 'message' => $safeMessage],
    ]);
    logMaintenance('restore_failed', $safeMessage, 'failed');
    writeAuditLog('restore_failed', 'Restore failed: ' . $safeMessage, 'failed', 'error', 'backup', $file ?? null);
    if (function_exists('writeAppLog')) writeAppLog('error', 'restore', 'Full restore failed', ['error' => $safeMessage]);
    header('Location: backup_center.php?status=error&message=' . urlencode('복원 실패: ' . $safeMessage));
}
exit;
