<?php

namespace App\Services;

use App\Models\NotificationSetting;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;

class NotificationService
{
    protected $settings;

    public function __construct()
    {
        $this->settings = NotificationSetting::getSettings();
    }

    /**
     * Send notification through all enabled channels
     */
    public function send(User $user, string $title, string $message, array $data = [])
    {
        $results = [];

        // Email is mandatory
        if ($this->settings->email_enabled) {
            $results['email'] = $this->sendEmail($user, $title, $message, $data);
        }

        // Push notification is optional
        if ($this->settings->push_enabled && $user->device_token) {
            $results['push'] = $this->sendPushNotification($user, $title, $message, $data);
        }

        // SMS is optional
        if ($this->settings->sms_enabled && $user->phone) {
            $results['sms'] = $this->sendSms($user, $title, $message);
        }

        return $results;
    }

    /**
     * Send email notification
     */
    public function sendEmail(User $user, string $subject, string $message, array $data = [])
    {
        try {
            $title = $subject;
            $viewData = compact('title', 'message', 'user', 'data');
            Mail::send('emails.notification', $viewData, function ($mail) use ($user, $subject) {
                'title' => $subject,
                'message' => $message,
                'user' => $user,
                'data' => $data
            ], function ($mail) use ($user, $subject) {
                $mail->to($user->email, $user->name)
                    ->subject($subject);
            });

            Log::info('Email sent successfully', ['user' => $user->email, 'subject' => $subject]);
            return ['success' => true, 'message' => 'Email sent successfully'];
        } catch (\Exception $e) {
            Log::error('Email send failed', ['error' => $e->getMessage(), 'user' => $user->email]);
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * Send push notification
     */
    public function sendPushNotification(User $user, string $title, string $body, array $data = [])
    {
        try {
            $provider = $this->settings->push_provider;

            if ($provider === 'firebase') {
                return $this->sendFirebasePush($user->device_token, $title, $body, $data);
            } elseif ($provider === 'onesignal') {
                return $this->sendOneSignalPush($user->device_token, $title, $body, $data);
            }

            return ['success' => false, 'message' => 'No push provider configured'];
        } catch (\Exception $e) {
            Log::error('Push notification failed', ['error' => $e->getMessage(), 'user' => $user->id]);
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * Send Firebase Cloud Messaging push notification
     */
    protected function sendFirebasePush(string $deviceToken, string $title, string $body, array $data = [])
    {
        $serverKey = $this->settings->push_server_key;

        $response = Http::withHeaders([
            'Authorization' => 'key=' . $serverKey,
            'Content-Type' => 'application/json',
        ])->post('https://fcm.googleapis.com/fcm/send', [
            'to' => $deviceToken,
            'notification' => [
                'title' => $title,
                'body' => $body,
                'sound' => 'default',
                'badge' => 1,
            ],
            'data' => $data,
        ]);

        if ($response->successful()) {
            Log::info('Firebase push sent successfully', ['device_token' => substr($deviceToken, 0, 20) . '...']);
            return ['success' => true, 'message' => 'Push notification sent'];
        }

        return ['success' => false, 'message' => 'Failed to send push notification'];
    }

    /**
     * Send OneSignal push notification
     */
    protected function sendOneSignalPush(string $deviceToken, string $title, string $body, array $data = [])
    {
        $appId = $this->settings->push_config['app_id'] ?? '';
        $apiKey = $this->settings->push_api_key;

        $response = Http::withHeaders([
            'Authorization' => 'Basic ' . $apiKey,
            'Content-Type' => 'application/json',
        ])->post('https://onesignal.com/api/v1/notifications', [
            'app_id' => $appId,
            'include_player_ids' => [$deviceToken],
            'headings' => ['en' => $title],
            'contents' => ['en' => $body],
            'data' => $data,
        ]);

        if ($response->successful()) {
            Log::info('OneSignal push sent successfully');
            return ['success' => true, 'message' => 'Push notification sent'];
        }

        return ['success' => false, 'message' => 'Failed to send push notification'];
    }

    /**
     * Send SMS notification
     */
    public function sendSms(User $user, string $title, string $message)
    {
        try {
            $provider = $this->settings->sms_provider;

            if ($provider === 'twilio') {
                return $this->sendTwilioSms($user->phone, $message);
            } elseif ($provider === 'nexmo') {
                return $this->sendNexmoSms($user->phone, $message);
            } elseif ($provider === 'africas_talking') {
                return $this->sendAfricasTalkingSms($user->phone, $message);
            }

            return ['success' => false, 'message' => 'No SMS provider configured'];
        } catch (\Exception $e) {
            Log::error('SMS send failed', ['error' => $e->getMessage(), 'phone' => $user->phone]);
            return ['success' => false, 'message' => $e->getMessage()];
        }
    }

    /**
     * Send SMS via Twilio
     */
    protected function sendTwilioSms(string $phone, string $message)
    {
        $accountSid = $this->settings->sms_api_key;
        $authToken = $this->settings->sms_api_secret;
        $fromNumber = $this->settings->sms_from_number;

        $response = Http::withBasicAuth($accountSid, $authToken)
            ->asForm()
            ->post("https://api.twilio.com/2010-04-01/Accounts/{$accountSid}/Messages.json", [
                'To' => $phone,
                'From' => $fromNumber,
                'Body' => $message,
            ]);

        if ($response->successful()) {
            Log::info('Twilio SMS sent successfully', ['phone' => $phone]);
            return ['success' => true, 'message' => 'SMS sent successfully'];
        }

        return ['success' => false, 'message' => 'Failed to send SMS'];
    }

    /**
     * Send SMS via Nexmo/Vonage
     */
    protected function sendNexmoSms(string $phone, string $message)
    {
        $apiKey = $this->settings->sms_api_key;
        $apiSecret = $this->settings->sms_api_secret;
        $fromNumber = $this->settings->sms_from_number;

        $response = Http::post('https://rest.nexmo.com/sms/json', [
            'api_key' => $apiKey,
            'api_secret' => $apiSecret,
            'from' => $fromNumber,
            'to' => $phone,
            'text' => $message,
        ]);

        if ($response->successful()) {
            Log::info('Nexmo SMS sent successfully', ['phone' => $phone]);
            return ['success' => true, 'message' => 'SMS sent successfully'];
        }

        return ['success' => false, 'message' => 'Failed to send SMS'];
    }

    /**
     * Send SMS via Africa's Talking
     */
    protected function sendAfricasTalkingSms(string $phone, string $message)
    {
        $apiKey = $this->settings->sms_api_key;
        $username = $this->settings->sms_config['username'] ?? '';
        $from = $this->settings->sms_from_number;

        $response = Http::withHeaders([
            'apiKey' => $apiKey,
            'Content-Type' => 'application/x-www-form-urlencoded',
        ])->asForm()->post('https://api.africastalking.com/version1/messaging', [
            'username' => $username,
            'to' => $phone,
            'message' => $message,
            'from' => $from,
        ]);

        if ($response->successful()) {
            Log::info('Africa\'s Talking SMS sent successfully', ['phone' => $phone]);
            return ['success' => true, 'message' => 'SMS sent successfully'];
        }

        return ['success' => false, 'message' => 'Failed to send SMS'];
    }
}

