<?php

require_once __DIR__ . '/functions.php';
require_once __DIR__ . '/functions_backup.php';

function adminBackupStatusFormatBytes($bytes) {
    $bytes = max(0, (int)$bytes);
    if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB';
    if ($bytes >= 1048576) return number_format($bytes / 1048576, 2) . ' MB';
    if ($bytes >= 1024) return number_format($bytes / 1024, 1) . ' KB';
    return number_format($bytes) . ' bytes';
}

function adminBackupStatusLabel($status) {
    return [
        'ok' => '정상',
        'warning' => '주의',
        'error' => '확인 필요',
    ][$status] ?? '주의';
}

function adminBackupStatusRecentErrorCount($days = 30) {
    try {
        $days = max(1, min(90, (int)$days));
        $stmt = getDBConnection()->prepare("
            SELECT COUNT(*)
            FROM app_logs
            WHERE created_at >= DATE_SUB(NOW(), INTERVAL {$days} DAY)
              AND log_level IN ('error', 'critical')
              AND (
                  log_type LIKE :backup_type
                  OR log_type LIKE :restore_type
                  OR log_type LIKE :import_type
                  OR log_type LIKE :export_type
              )
        ");
        $stmt->bindValue(':backup_type', '%backup%', PDO::PARAM_STR);
        $stmt->bindValue(':restore_type', '%restore%', PDO::PARAM_STR);
        $stmt->bindValue(':import_type', '%import%', PDO::PARAM_STR);
        $stmt->bindValue(':export_type', '%export%', PDO::PARAM_STR);
        $stmt->execute();
        return (int)$stmt->fetchColumn();
    } catch (Throwable $e) {
        return 0;
    }
}

function getAdminBackupStatusSummary() {
    $summary = [
        'status' => 'warning',
        'label' => '주의',
        'storage_writable' => false,
        'backup_count' => 0,
        'file_count' => 0,
        'valid_count' => 0,
        'invalid_count' => 0,
        'abnormal_count' => 0,
        'failed_count' => 0,
        'total_size' => 0,
        'total_size_text' => '0 bytes',
        'latest' => null,
        'latest_at' => null,
        'latest_age_days' => null,
        'latest_size_text' => '-',
        'restore_ready' => false,
        'restore_label' => '확인 필요',
        'message' => '백업 상태를 확인해야 합니다.',
        'issues' => [],
    ];

    try {
        $dir = ensureBackupStorage();
        $summary['storage_writable'] = is_writable($dir);
        $files = listBackupFiles();
    } catch (Throwable $e) {
        $summary['issues'][] = '백업 저장소를 확인할 수 없습니다.';
        $summary['message'] = '백업 저장소 확인이 필요합니다.';
        $summary['status'] = 'error';
        $summary['label'] = adminBackupStatusLabel('error');
        return $summary;
    }

    $summary['file_count'] = count($files);
    $fullBackups = [];
    foreach ($files as $file) {
        $name = (string)($file['file_name'] ?? '');
        $size = (int)($file['file_size'] ?? 0);
        $summary['total_size'] += $size;
        if (!empty($file['valid'])) $summary['valid_count']++;
        else $summary['invalid_count']++;
        if ($size > 0 && $size < 1024) $summary['abnormal_count']++;

        $isFullBackup = strpos($name, 'music_backup_') === 0
            || in_array((string)($file['export_type'] ?? ''), ['full_db', 'melonlite_json_backup'], true);
        if ($isFullBackup) {
            $fullBackups[] = $file;
        }
    }
    $summary['total_size_text'] = adminBackupStatusFormatBytes($summary['total_size']);
    $summary['backup_count'] = count($fullBackups);
    $summary['failed_count'] = adminBackupStatusRecentErrorCount(30);

    usort($fullBackups, function ($a, $b) {
        return (int)($b['modified_at'] ?? 0) <=> (int)($a['modified_at'] ?? 0);
    });
    $latest = $fullBackups[0] ?? null;
    if ($latest) {
        $mtime = (int)($latest['modified_at'] ?? 0);
        $summary['latest'] = [
            'file_name' => basename((string)($latest['file_name'] ?? '')),
            'valid' => !empty($latest['valid']),
            'file_size' => (int)($latest['file_size'] ?? 0),
            'export_type' => (string)($latest['export_type'] ?? 'full_db'),
        ];
        $summary['latest_at'] = $mtime > 0 ? date('Y-m-d H:i', $mtime) : null;
        $summary['latest_age_days'] = $mtime > 0 ? (int)floor((time() - $mtime) / 86400) : null;
        $summary['latest_size_text'] = adminBackupStatusFormatBytes((int)($latest['file_size'] ?? 0));
    }

    if (!$summary['storage_writable']) {
        $summary['issues'][] = '백업 저장소에 쓸 수 없습니다.';
    }
    if ($summary['backup_count'] <= 0) {
        $summary['issues'][] = '복구에 사용할 DB 백업이 없습니다.';
    }
    if ($latest && empty($latest['valid'])) {
        $summary['issues'][] = '최근 DB 백업 검증이 실패했습니다.';
    }
    if ($latest && (int)($latest['file_size'] ?? 0) < 1024) {
        $summary['issues'][] = '최근 DB 백업 크기가 비정상적으로 작습니다.';
    }
    if ($summary['failed_count'] > 0) {
        $summary['issues'][] = '최근 30일 백업/복구 관련 실패 로그가 있습니다.';
    }
    if ($summary['latest_age_days'] !== null && $summary['latest_age_days'] >= 14) {
        $summary['issues'][] = '최근 DB 백업이 14일 이상 오래되었습니다.';
    }

    $summary['restore_ready'] = $summary['backup_count'] > 0
        && $summary['storage_writable']
        && $latest
        && !empty($latest['valid'])
        && (int)($latest['file_size'] ?? 0) >= 1024;

    $status = 'ok';
    if (!$summary['restore_ready'] || $summary['invalid_count'] > 0 || $summary['abnormal_count'] > 0) {
        $status = 'error';
    } elseif ($summary['failed_count'] > 0 || ($summary['latest_age_days'] !== null && $summary['latest_age_days'] >= 7)) {
        $status = 'warning';
    }

    $summary['status'] = $status;
    $summary['label'] = adminBackupStatusLabel($status);
    $summary['restore_label'] = $summary['restore_ready'] ? '복구 준비됨' : '복구 준비 확인 필요';
    if ($status === 'ok') {
        $summary['message'] = '최근 DB 백업과 복구 준비 상태가 정상입니다.';
    } elseif ($status === 'warning') {
        $summary['message'] = '백업 상태에 주의가 필요한 항목이 있습니다.';
    } else {
        $summary['message'] = '복구 준비 상태 확인이 필요합니다.';
    }

    return $summary;
}

function syncAdminBackupStatusNotification($summary) {
    if (!function_exists('upsertAdminNotification')) return;
    $status = (string)($summary['status'] ?? 'ok');
    if ($status === 'ok') return;

    try {
        upsertAdminNotification([
            'fingerprint' => sha1('backup_status|restore_readiness'),
            'category' => 'backup',
            'level' => $status === 'error' ? 'error' : 'warning',
            'status' => 'active',
            'title' => '백업 상태 확인 필요',
            'message' => (string)($summary['message'] ?? '백업 상태를 확인해야 합니다.'),
            'detail' => 'DB 백업 ' . number_format((int)($summary['backup_count'] ?? 0)) . '개 / 실패 로그 ' . number_format((int)($summary['failed_count'] ?? 0)) . '건',
            'related_type' => 'backup_status',
            'related_url' => 'backup_center.php#backup-status-summary',
            'is_pinned' => $status === 'error' ? 1 : 0,
        ]);
    } catch (Throwable $e) {
        if (function_exists('writeAppLog')) {
            writeAppLog('warning', 'backup_status', 'Backup status notification sync failed', [
                'error' => limitLogText($e->getMessage(), 300),
            ]);
        }
    }
}
