<?php

namespace App\Services;

use App\Models\Setting;
use App\Models\User;
use App\Models\UserFcmToken;
use Google\Client;
use Google\Exception;
use Illuminate\Http\Request as HttpRequest;
use RuntimeException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Storage;
use Throwable;

class NotificationService {
    /**
     * @param array $registrationIDs
     * @param string|null $title
     * @param string|null $message
     * @param string $type
     * @param array $customBodyFields
     * @return string|array|bool
     */
    public static function sendFcmNotification(
    array $registrationIDs,
    string|null $title = '',
    string|null $message = '',
    string $type = "default",
    array $customBodyFields = [],
    bool $sendToAll = false
    ): string|array|bool {
    try {
        $project_id = Setting::select('value')->where('name', 'firebase_project_id')->first();
        if (empty($project_id->value)) {
            return ['error' => true, 'message' => 'FCM configurations are not configured.'];
        }
        $project_id = $project_id->value;
        $url = 'https://fcm.googleapis.com/v1/projects/' . $project_id . '/messages:send';

        $access_token = self::getAccessToken();
        if ($access_token['error']) {
            return $access_token;
        }
        $dataWithTitle = [
            ...$customBodyFields,
            "title" => $title,
            "body"  => $message,
            "type"  => $type,
        ];



        // ✅ Case 1: Send to all (topic-based)
        if ($sendToAll) {

            $data = [
                "message" => [
                    "topic" => "allUsers", // universal topic (subscribe everyone here)
                    "data"  => self::convertToStringRecursively($dataWithTitle),
                    "notification" => [
                        "title" => $title,
                        "body"  => $message
                    ]
                ]
            ];

            $encodedData = json_encode($data);
            $headers = [
                'Authorization: Bearer ' . $access_token['data'],
                'Content-Type: application/json',
            ];
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedData);

            $result = curl_exec($ch);
            if (!$result) {
                return ['error' => true, 'message' => 'Curl failed: ' . curl_error($ch)];
            }
            curl_close($ch);
            return ['error' => false, 'message' => "Bulk notification sent via topic", 'data' => $result];
        }

        // ✅ Case 2: Send individually (like existing code)
        $deviceInfo = UserFcmToken::with('user')
            ->select(['platform_type', 'fcm_token'])
            ->whereIn('fcm_token', $registrationIDs)
            ->whereHas('user', fn($q) => $q->where('notification', 1))
            ->get();

        // ✅ Log all targeted users and their FCM tokens before sending
        try {
            // Log::info('🔔 Device Info for Notification', $deviceInfo->toArray());
        } catch (Throwable $e) {
            Log::error('Failed to log device info: ' . $e->getMessage());
        }


        $result = [];
        foreach ($registrationIDs as $registrationID) {
            $platform = $deviceInfo->first(fn($q) => $q->fcm_token == $registrationID);
            if (!$platform) continue;
             $data = [
            'message' => [
                'token' => $registrationID,

                // Notification block (title & body)
                'notification' => [
                    'title' => $title,
                    'body'  => $message,
                ],

                // Custom data (ALL values must be strings)
                'data' => self::convertToStringRecursively($dataWithTitle),

                // Android config
                'android' => [
                    'priority' => 'high',
                    'notification' => [
                        'image' => !empty($dataWithTitle['image']) ? $dataWithTitle['image'] : null,
                    ],
                ],

                // iOS (APNs) config
                'apns' => [
                    'headers' => [
                        'apns-priority' => '10',
                    ],
                    'payload' => [
                        'aps' => [
                            'alert' => [
                                'title' => $title,
                                'body'  => $message,
                            ],
                            'sound' => 'default',
                            'mutable-content' => 1, // REQUIRED for images
                        ],
                    ],
                    'fcm_options' => [
                        'image' => !empty($dataWithTitle['image']) ? $dataWithTitle['image'] : null,
                    ],
                ],
                ],
            ];


            $encodedData = json_encode($data);
            $headers = [
                'Authorization: Bearer ' . $access_token['data'],
                'Content-Type: application/json',
            ];

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedData);

            $result[] = curl_exec($ch);
            curl_close($ch);
        }

        return ['error' => false, 'message' => "Individual notifications sent", 'data' => $result];
    } catch (Throwable $th) {
        throw new RuntimeException($th);
    }
}

    public static function getAccessToken() {
        try {
            $file_name = Setting::select('value')->where('name', 'service_file')->first();
            if (empty($file_name)) {
                return [
                    'error'   => true,
                    'message' => 'FCM Configuration not found'
                ];
            }
            $disk = config('filesystems.default');
            $file = $file_name->value;

            if ($disk === 'local' || $disk === 'public') {
                // LOCAL STORAGE
                $file_path = Storage::disk($disk)->path($file);

            } else {
                // S3 (or any cloud disk)
                // Download file to local temp
                $fileContent = Storage::disk($disk)->get($file);
                $file_path = storage_path('app/firebase_service.json');
                file_put_contents($file_path, $fileContent);
            }

            if (!file_exists($file_path)) {
                return [
                    'error'   => true,
                    'message' => 'FCM Service File not found'
                ];
            }
            $client = new Client();
            $client->setAuthConfig($file_path);
            $client->setScopes(['https://www.googleapis.com/auth/firebase.messaging']);

            return [
                'error'   => false,
                'message' => 'Access Token generated successfully',
                'data'    => $client->fetchAccessTokenWithAssertion()['access_token']
            ];

        } catch (Exception $e) {
            throw new RuntimeException($e);
        }
    }

    public static function convertToStringRecursively($data, &$flattenedArray = []) {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                self::convertToStringRecursively($value, $flattenedArray);
            } elseif (is_null($value)) {
                $flattenedArray[$key] = '';
            } else {
                $flattenedArray[$key] = (string)$value;
            }
        }
        return $flattenedArray;
    }
   public static function sendNewDeviceLoginEmail(User $user, HttpRequest $request)
    {
        try {
            Log::info("sending New device login alert");

            $deviceType = ucfirst($request->platform_type ?? 'Unknown');
            $ip = request()->ip();
            $loginTime = now()->format('d M Y - h:i A');

            // Fetch company name
            $companyName = Setting::where('name', 'company_name')->value('value') ?? 'Unknown';

            // Email message
            $message =
                "A new device has just logged in to your {$companyName} account.\n\n" .
                "⏰ Login Time: {$loginTime}\n\n";

            Mail::raw($message, function ($msg) use ($user, $companyName) {
                $msg->to($user->email)
                    ->from('admin@yourdomain.com', $companyName)
                    ->subject("New Device Login Detected - {$companyName}");
            });

            Log::info("New device login alert sent to: {$user->email}");
        } catch (\Exception $e) {
            Log::error("Failed to send new device login email: " . $e->getMessage());
        }
    }


}
