<?php

namespace App\Console\Commands;

use App\Services\SlackNotificationService;
use App\Services\Stats\StatMonitorService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

class BackupCheckCommand extends Command
{
    protected $signature = 'db:backup-check
                            {--path= : 백업 경로 오버라이드}';

    protected $description = 'DB 백업 상태를 확인하고 이상 시 알림을 생성합니다';

    public function handle(StatMonitorService $monitorService): int
    {
        $this->info('DB 백업 상태 확인 시작...');

        $statusFile = $this->option('path')
            ? rtrim($this->option('path'), '/') . '/.backup_status'
            : env('BACKUP_STATUS_FILE', '/data/backup/mysql/.backup_status');

        $errors = [];

        // 1. 상태 파일 존재 여부
        if (! file_exists($statusFile)) {
            $errors[] = '백업 상태 파일 없음: ' . $statusFile;
            $this->reportErrors($monitorService, $errors);

            return self::FAILURE;
        }

        $status = json_decode(file_get_contents($statusFile), true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            $errors[] = '상태 파일 JSON 파싱 실패: ' . json_last_error_msg();
            $this->reportErrors($monitorService, $errors);

            return self::FAILURE;
        }

        // 2. last_run이 25시간 이내인지
        $lastRun = strtotime($status['last_run'] ?? '');
        if (! $lastRun || (time() - $lastRun) > 25 * 3600) {
            $lastRunStr = $status['last_run'] ?? 'unknown';
            $errors[] = "마지막 백업이 25시간 초과: {$lastRunStr}";
        }

        // 3. status가 success인지
        if (($status['status'] ?? '') !== 'success') {
            $errors[] = '백업 상태 실패: ' . ($status['status'] ?? 'unknown');
        }

        // 4. 각 DB 백업 파일 크기 검증
        $minSizes = [
            'sam' => (int) env('BACKUP_MIN_SIZE_SAM', 1048576),
            'sam_stat' => (int) env('BACKUP_MIN_SIZE_STAT', 102400),
        ];

        $databases = $status['databases'] ?? [];
        foreach ($minSizes as $dbName => $minSize) {
            if (! isset($databases[$dbName])) {
                $errors[] = "{$dbName} DB 백업 정보 없음";

                continue;
            }

            $sizeBytes = $databases[$dbName]['size_bytes'] ?? 0;
            if ($sizeBytes < $minSize) {
                $errors[] = "{$dbName} 백업 파일 크기 부족: {$sizeBytes} bytes (최소 {$minSize})";
            }
        }

        // 결과 처리
        if (! empty($errors)) {
            $this->reportErrors($monitorService, $errors);

            return self::FAILURE;
        }

        $this->info('✅ DB 백업 상태 정상');
        Log::info('db:backup-check 정상', [
            'last_run' => $status['last_run'],
            'databases' => array_keys($databases),
        ]);

        return self::SUCCESS;
    }

    private function reportErrors(StatMonitorService $monitorService, array $errors): void
    {
        $errorMessage = implode("\n", $errors);

        $this->error('❌ DB 백업 이상 감지:');
        foreach ($errors as $error) {
            $this->error("  - {$error}");
        }

        // stat_alerts에 기록
        $monitorService->recordBackupFailure(
            '[backup] DB 백업 이상 감지',
            $errorMessage
        );

        // Slack 알림 전송
        app(SlackNotificationService::class)->sendBackupAlert(
            'DB 백업 이상 감지',
            $errorMessage
        );

        Log::error('db:backup-check 실패', ['errors' => $errors]);
    }
}