<?php

namespace App\Services;

use App\Models\FcmSendLog;
use App\Models\PushDeviceToken;
use App\Services\Fcm\FcmSender;

class AdminFcmService extends Service
{
    public function __construct(
        private readonly FcmSender $fcmSender
    ) {}

    /**
     * 관리자 FCM 발송
     *
     * @param  array  $data  발송 데이터
     * @param  int|null  $senderId  발송자 ID (MNG 관리자)
     */
    public function send(array $data, ?int $senderId = null): array
    {
        // 대상 토큰 조회
        $query = PushDeviceToken::withoutGlobalScopes()->active();

        if (! empty($data['tenant_id'])) {
            $query->forTenant($data['tenant_id']);
        }

        if (! empty($data['user_id'])) {
            $query->forUser($data['user_id']);
        }

        if (! empty($data['platform'])) {
            $query->platform($data['platform']);
        }

        $tokens = $query->pluck('token')->toArray();
        $tokenCount = count($tokens);

        if ($tokenCount === 0) {
            return [
                'success' => false,
                'message' => __('error.fcm.no_tokens'),
                'data' => null,
            ];
        }

        // 발송 로그 생성
        $sendLog = FcmSendLog::create([
            'tenant_id' => $data['tenant_id'] ?? null,
            'user_id' => $data['user_id'] ?? null,
            'sender_id' => $senderId,
            'title' => $data['title'],
            'body' => $data['body'],
            'channel_id' => $data['channel_id'] ?? 'push_default',
            'type' => $data['type'] ?? null,
            'platform' => $data['platform'] ?? null,
            'data' => array_filter([
                'type' => $data['type'] ?? null,
                'url' => $data['url'] ?? null,
                'sound_key' => $data['sound_key'] ?? null,
            ]),
            'status' => FcmSendLog::STATUS_SENDING,
        ]);

        try {
            // FCM 발송
            $fcmData = array_filter([
                'type' => $data['type'] ?? null,
                'url' => $data['url'] ?? null,
                'sound_key' => $data['sound_key'] ?? null,
            ]);

            $result = $this->fcmSender->sendToMany(
                $tokens,
                $data['title'],
                $data['body'],
                $data['channel_id'] ?? 'push_default',
                $fcmData
            );

            // 무효 토큰 비활성화
            $invalidTokens = $result->getInvalidTokens();
            if (count($invalidTokens) > 0) {
                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(),
                        ]);
                }
            }

            // 발송 로그 업데이트
            $summary = $result->toSummary();
            $sendLog->markAsCompleted($summary);

            return [
                'success' => true,
                'message' => __('message.fcm.sent'),
                'data' => $summary,
                'log_id' => $sendLog->id,
            ];

        } catch (\Exception $e) {
            $sendLog->markAsFailed($e->getMessage());

            return [
                'success' => false,
                'message' => __('error.fcm.send_failed'),
                'error' => $e->getMessage(),
                'log_id' => $sendLog->id,
            ];
        }
    }

    /**
     * 대상 토큰 수 미리보기
     */
    public function previewCount(array $filters): int
    {
        $query = PushDeviceToken::withoutGlobalScopes()->active();

        if (! empty($filters['tenant_id'])) {
            $query->forTenant($filters['tenant_id']);
        }

        if (! empty($filters['user_id'])) {
            $query->forUser($filters['user_id']);
        }

        if (! empty($filters['platform'])) {
            $query->platform($filters['platform']);
        }

        return $query->count();
    }

    /**
     * 토큰 목록 조회 (관리자용)
     */
    public function getTokens(array $filters, int $perPage = 20): array
    {
        $query = PushDeviceToken::withoutGlobalScopes()
            ->with(['user:id,name,email', 'tenant:id,company_name']);

        if (! empty($filters['tenant_id'])) {
            $query->where('tenant_id', $filters['tenant_id']);
        }

        if (! empty($filters['platform'])) {
            $query->where('platform', $filters['platform']);
        }

        if (isset($filters['is_active'])) {
            $query->where('is_active', $filters['is_active']);
        }

        if (! empty($filters['has_error'])) {
            $query->hasError();
        }

        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('token', 'like', "%{$search}%")
                    ->orWhere('device_name', 'like', "%{$search}%")
                    ->orWhereHas('user', function ($q) use ($search) {
                        $q->where('name', 'like', "%{$search}%")
                            ->orWhere('email', 'like', "%{$search}%");
                    });
            });
        }

        return $query->orderBy('created_at', 'desc')
            ->paginate($perPage)
            ->toArray();
    }

    /**
     * 토큰 통계
     */
    public function getTokenStats(?int $tenantId = null): array
    {
        $query = PushDeviceToken::withoutGlobalScopes();

        if ($tenantId) {
            $query->where('tenant_id', $tenantId);
        }

        $total = (clone $query)->count();
        $active = (clone $query)->where('is_active', true)->count();
        $inactive = (clone $query)->where('is_active', false)->count();
        $hasError = (clone $query)->whereNotNull('last_error')->count();

        $byPlatform = (clone $query)->selectRaw('platform, count(*) as count')
            ->groupBy('platform')
            ->pluck('count', 'platform')
            ->toArray();

        return [
            'total' => $total,
            'active' => $active,
            'inactive' => $inactive,
            'has_error' => $hasError,
            'by_platform' => $byPlatform,
        ];
    }

    /**
     * 토큰 상태 토글
     */
    public function toggleToken(int $tokenId): PushDeviceToken
    {
        $token = PushDeviceToken::withoutGlobalScopes()->findOrFail($tokenId);
        $token->update(['is_active' => ! $token->is_active]);

        return $token;
    }

    /**
     * 토큰 삭제
     */
    public function deleteToken(int $tokenId): bool
    {
        $token = PushDeviceToken::withoutGlobalScopes()->findOrFail($tokenId);

        return $token->delete();
    }

    /**
     * 발송 이력 조회
     */
    public function getHistory(array $filters, int $perPage = 20): array
    {
        $query = FcmSendLog::with(['sender:id,name', 'tenant:id,company_name']);

        if (! empty($filters['tenant_id'])) {
            $query->where('tenant_id', $filters['tenant_id']);
        }

        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        if (! empty($filters['from'])) {
            $query->whereDate('created_at', '>=', $filters['from']);
        }

        if (! empty($filters['to'])) {
            $query->whereDate('created_at', '<=', $filters['to']);
        }

        return $query->orderBy('created_at', 'desc')
            ->paginate($perPage)
            ->toArray();
    }
}
