<?php

namespace Kylin\Notification\Channels;

use GuzzleHttp\Client;
use Kylin\Notification\Contracts\ChannelInterface;
use Kylin\Notification\Models\Notification;

/**
 * Firebase Cloud Messaging 渠道
 * 通过 HTTP v1 API 直接调用
 * API文档：https://firebase.google.com/docs/cloud-messaging/send-message
 */
class FcmChannel implements ChannelInterface
{
    public function send(Notification $notification, array $params = []): array
    {
        try {
            $config = config('kylin-notification.channels.fcm', []);
            $serviceAccountPath = $config['service_account_path'] ?? '';
            $projectId = $config['project_id'] ?? '';

            if (!$projectId) {
                return ['success' => false, 'message_id' => null, 'error' => 'FCM not configured', 'raw_response' => null];
            }

            // 获取 access token
            $accessToken = $this->getAccessToken($serviceAccountPath, $config);

            // 构建消息
            $message = [
                'message' => [
                    'token' => $params['token'] ?? '',
                    'notification' => [
                        'title' => $params['title'] ?? $notification->title,
                        'body' => $params['body'] ?? $notification->content,
                    ],
                    'data' => $params['data'] ?? [],
                ],
            ];

            // 如果是 topic 推送
            if (isset($params['topic'])) {
                unset($message['message']['token']);
                $message['message']['topic'] = $params['topic'];
            }

            // 如果是 condition 推送
            if (isset($params['condition'])) {
                unset($message['message']['token']);
                $message['message']['condition'] = $params['condition'];
            }

            $client = new Client();
            $response = $client->post("https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send", [
                'headers' => [
                    'Authorization' => "Bearer {$accessToken}",
                    'Content-Type' => 'application/json',
                ],
                'json' => $message,
            ]);

            $result = json_decode($response->getBody()->getContents(), true);

            return [
                'success' => true,
                'message_id' => $result['name'] ?? null,
                'error' => null,
                'raw_response' => $result,
            ];
        } catch (\Throwable $e) {
            return ['success' => false, 'message_id' => null, 'error' => $e->getMessage(), 'raw_response' => null];
        }
    }

    public function getName(): string
    {
        return 'fcm';
    }

    private function getAccessToken(string $serviceAccountPath, array $config): string
    {
        // 如果有缓存的 access token，直接返回
        $cacheKey = 'kylin_notification_fcm_token';
        if ($cached = cache($cacheKey)) {
            return $cached;
        }

        // 使用服务账号获取 access token
        $clientEmail = $config['client_email'] ?? '';
        $privateKey = $config['private_key'] ?? '';

        if ($clientEmail && $privateKey) {
            $now = time();
            $jwt = $this->createJwt($clientEmail, $privateKey, $now);
            $client = new Client();
            $response = $client->post('https://oauth2.googleapis.com/token', [
                'form_params' => [
                    'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
                    'assertion' => $jwt,
                ],
            ]);
            $result = json_decode($response->getBody()->getContents(), true);
            $token = $result['access_token'];
            $expiresIn = ($result['expires_in'] ?? 3600) - 60;
            cache([$cacheKey => $token], $expiresIn);
            return $token;
        }

        throw new \RuntimeException('FCM access token cannot be obtained');
    }

    private function createJwt(string $clientEmail, string $privateKey, int $now): string
    {
        $header = base64_encode(json_encode(['alg' => 'RS256', 'typ' => 'JWT']));
        $payload = base64_encode(json_encode([
            'iss' => $clientEmail,
            'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
            'aud' => 'https://oauth2.googleapis.com/token',
            'iat' => $now,
            'exp' => $now + 3600,
        ]));

        openssl_sign("{$header}.{$payload}", $signature, $privateKey, OPENSSL_ALGO_SHA256);

        return "{$header}.{$payload}." . base64_encode($signature);
    }
}
