<?php

namespace App\Services;

use App\Models\Notification;
use App\Models\SystemConfiguration;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;

class NotificationService
{
    /**
     * Send notification to user or admin
     */
    public static function send($notifiable, $type, $data, $channels = [])
    {
        // Create notification in database
        $notification = Notification::create([
            'notifiable_type' => get_class($notifiable),
            'notifiable_id' => $notifiable->id,
            'type' => $type,
            'data' => $data,
        ]);

        // Send through configured channels
        if (empty($channels)) {
            $channels = ['database']; // Default to database only
        }

        foreach ($channels as $channel) {
            switch ($channel) {
                case 'email':
                    self::sendEmail($notifiable, $type, $data, $notification);
                    break;
                case 'sms':
                    self::sendSMS($notifiable, $type, $data, $notification);
                    break;
                case 'push':
                    self::sendPushNotification($notifiable, $type, $data, $notification);
                    break;
            }
        }

        return $notification;
    }

    /**
     * Send email notification
     */
    private static function sendEmail($notifiable, $type, $data, $notification)
    {
        // Check if email notifications are enabled
        $emailEnabled = SystemConfiguration::findByKey('notifications.email.enabled');
        if (!$emailEnabled || !$emailEnabled->value) {
            return;
        }

        $emailTemplate = SystemConfiguration::findByKey('notifications.email.template_' . $type);
        if (!$emailTemplate) {
            return;
        }

        // Send email logic here
        try {
            \Mail::send('emails.notification', [
                'user' => $notifiable,
                'notification' => $notification,
                'data' => $data,
                'type' => $type,
            ], function ($message) use ($notifiable) {
                $message->to($notifiable->email)
                    ->subject('Notification');
            });
        } catch (\Exception $e) {
            \Log::error('Failed to send email notification: ' . $e->getMessage());
        }
    }

    /**
     * Send SMS notification
     */
    private static function sendSMS($notifiable, $type, $data, $notification)
    {
        // Check if SMS notifications are enabled
        $smsEnabled = SystemConfiguration::findByKey('notifications.sms.enabled');
        if (!$smsEnabled || !$smsEnabled->value) {
            return;
        }

        $smsTemplate = SystemConfiguration::findByKey('notifications.sms.template_' . $type);
        if (!$smsTemplate) {
            return;
        }

        $provider = SystemConfiguration::findByKey('notifications.sms.provider');
        $providerName = $provider ? $provider->value : 'twilio';

        // Send SMS logic
        try {
            $message = self::buildSMSMessage($smsTemplate->value, $data);

            if ($providerName === 'twilio') {
                self::sendViaTwilio($notifiable->phone, $message);
            } else {
                self::sendViaSMSProvider($notifiable->phone, $message, $providerName);
            }

            // Log SMS sent
            \Log::info('SMS sent to ' . $notifiable->phone);
        } catch (\Exception $e) {
            \Log::error('Failed to send SMS notification: ' . $e->getMessage());
        }
    }

    /**
     * Send push notification
     */
    private static function sendPushNotification($notifiable, $type, $data, $notification)
    {
        // Check if push notifications are enabled
        $pushEnabled = SystemConfiguration::findByKey('notifications.push.enabled');
        if (!$pushEnabled || !$pushEnabled->value) {
            return;
        }

        try {
            // Send push notification logic here
            // This would integrate with FCM or similar service
            if ($notifiable->fcm_token) {
                // Send to FCM
                \Log::info('Push notification sent to ' . $notifiable->id);
            }
        } catch (\Exception $e) {
            \Log::error('Failed to send push notification: ' . $e->getMessage());
        }
    }

    /**
     * Build SMS message from template
     */
    private static function buildSMSMessage($template, $data)
    {
        $message = $template;

        foreach ($data as $key => $value) {
            $message = str_replace('{' . $key . '}', $value, $message);
        }

        return $message;
    }

    /**
     * Send via Twilio
     */
    private static function sendViaTwilio($phone, $message)
    {
        $accountSid = config('services.twilio.account_sid');
        $authToken = config('services.twilio.auth_token');
        $fromNumber = config('services.twilio.from_number');

        if (!$accountSid || !$authToken) {
            return;
        }

        try {
            $client = new \Twilio\Rest\Client($accountSid, $authToken);
            $client->messages->create($phone, [
                'from' => $fromNumber,
                'body' => $message,
            ]);
        } catch (\Exception $e) {
            \Log::error('Twilio error: ' . $e->getMessage());
        }
    }

    /**
     * Send via other SMS providers
     */
    private static function sendViaSMSProvider($phone, $message, $provider)
    {
        // Implement other SMS providers here (AWS SNS, Nexmo, etc.)
        \Log::info('SMS via ' . $provider . ' sent to ' . $phone);
    }

    /**
     * Get unread notifications for user
     */
    public static function getUnreadNotifications($user)
    {
        return Notification::where('notifiable_type', get_class($user))
            ->where('notifiable_id', $user->id)
            ->whereNull('read_at')
            ->latest()
            ->get();
    }

    /**
     * Get all notifications for user
     */
    public static function getAllNotifications($user, $limit = 50)
    {
        return Notification::where('notifiable_type', get_class($user))
            ->where('notifiable_id', $user->id)
            ->latest()
            ->limit($limit)
            ->get();
    }

    /**
     * Mark notification as read
     */
    public static function markAsRead($notificationId)
    {
        $notification = Notification::find($notificationId);
        if ($notification) {
            $notification->markAsRead();
        }
        return $notification;
    }

    /**
     * Mark all as read
     */
    public static function markAllAsRead($user)
    {
        Notification::where('notifiable_type', get_class($user))
            ->where('notifiable_id', $user->id)
            ->whereNull('read_at')
            ->update(['read_at' => now()]);
    }
}

