<?php

namespace App\Console\Commands;

use App\Models\PushDeviceToken;
use App\Services\Fcm\FcmSender;
use Illuminate\Console\Command;

class FcmSendCommand extends Command
{
    protected $signature = 'fcm:send
                            {--tenant= : 테넌트 ID (미지정 시 전체)}
                            {--user= : 사용자 ID (미지정 시 전체)}
                            {--platform= : 플랫폼 (android, ios, web)}
                            {--channel=push_default : 알림 채널 (push_default, push_vendor_register, push_approval_request, push_income, push_sales_order, push_purchase_order, push_contract)}
                            {--title= : 알림 제목 (필수)}
                            {--body= : 알림 내용 (필수)}
                            {--type= : 알림 타입 (invoice_failed 등)}
                            {--url= : 클릭 시 이동 URL}
                            {--sound-key= : 사운드 키 (invoice_failed 등)}
                            {--dry-run : 실제 발송 없이 대상 수만 출력}
                            {--limit=1000 : 최대 발송 수}';

    protected $description = 'FCM 푸시 알림 대량 발송';

    public function handle(): int
    {
        $title = $this->option('title');
        $body = $this->option('body');

        if (empty($title) || empty($body)) {
            $this->error('--title과 --body는 필수입니다.');

            return self::FAILURE;
        }

        // 대상 토큰 조회
        $query = PushDeviceToken::withoutGlobalScopes()->active();

        if ($tenantId = $this->option('tenant')) {
            $query->forTenant((int) $tenantId);
        }

        if ($userId = $this->option('user')) {
            $query->forUser((int) $userId);
        }

        if ($platform = $this->option('platform')) {
            $query->platform($platform);
        }

        $limit = (int) $this->option('limit');
        $tokens = $query->limit($limit)->pluck('token', 'id')->toArray();
        $tokenCount = count($tokens);

        if ($tokenCount === 0) {
            $this->warn('발송 대상 토큰이 없습니다.');

            return self::SUCCESS;
        }

        // 발송 정보 출력
        $this->info('FCM 대량 발송');
        $this->line('');
        $this->table(['항목', '값'], [
            ['대상 토큰 수', $tokenCount],
            ['테넌트', $this->option('tenant') ?: '전체'],
            ['사용자', $this->option('user') ?: '전체'],
            ['플랫폼', $this->option('platform') ?: '전체'],
            ['채널', $this->option('channel')],
            ['제목', $title],
            ['내용', mb_substr($body, 0, 30).(mb_strlen($body) > 30 ? '...' : '')],
            ['타입', $this->option('type') ?: '(없음)'],
            ['URL', $this->option('url') ?: '(없음)'],
        ]);
        $this->line('');

        // Dry-run 모드
        if ($this->option('dry-run')) {
            $this->info("🔍 Dry-run: {$tokenCount}개 토큰 발송 예정");

            return self::SUCCESS;
        }

        // 확인
        if (! $this->confirm("정말 {$tokenCount}개 토큰에 발송하시겠습니까?")) {
            $this->info('취소되었습니다.');

            return self::SUCCESS;
        }

        // payload 데이터 구성
        $data = array_filter([
            'type' => $this->option('type'),
            'url' => $this->option('url'),
            'sound_key' => $this->option('sound-key'),
        ]);

        // 발송 실행
        $this->info('발송 중...');
        $bar = $this->output->createProgressBar($tokenCount);
        $bar->start();

        $sender = new FcmSender;
        $channel = $this->option('channel');
        $tokenValues = array_values($tokens);
        $tokenIds = array_keys($tokens);

        $result = $sender->sendToMany($tokenValues, $title, $body, $channel, $data);

        $bar->finish();
        $this->line('');
        $this->line('');

        // 무효 토큰 처리
        $invalidTokens = $result->getInvalidTokens();
        if (count($invalidTokens) > 0) {
            $this->info('무효 토큰 비활성화 중...');

            // 토큰 값으로 DB 업데이트
            foreach ($invalidTokens as $token) {
                $response = $result->getResponse($token);
                $errorCode = $response?->getErrorCode();

                PushDeviceToken::withoutGlobalScopes()
                    ->where('token', $token)
                    ->update([
                        'is_active' => false,
                        'last_error' => $errorCode,
                        'last_error_at' => now(),
                    ]);
            }

            $this->warn('  비활성화된 토큰: '.count($invalidTokens).'개');
        }

        // 결과 출력
        $summary = $result->toSummary();
        $this->line('');
        $this->info('✅ 발송 완료');
        $this->table(['항목', '값'], [
            ['전체', $summary['total']],
            ['성공', $summary['success']],
            ['실패', $summary['failure']],
            ['무효 토큰', $summary['invalid_tokens']],
            ['성공률', $summary['success_rate'].'%'],
        ]);

        return self::SUCCESS;
    }
}
