<?php

namespace App\Http\Controllers\Admin\Settings\Notification;

use App\Enums\NotificationType;
use App\Enums\NotifyEventType;
use App\Http\Controllers\Controller;
use App\Models\Notification;
use App\Models\NotificationTemplate;
use App\Models\User;
use App\Services\Firebase\FirebaseNotificationService;
use App\Services\Helper\JsonHelper;
use App\Services\ModalIndexQuey;
use App\Services\Sms\SmsInterface;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;

class ServicesController extends Controller
{
    public function index()
    {
        adminUserHasPermission(permission: 'read');

        $service = request()->get('service', 'global-template');

        $buttons = [
            [
                'title' => __('Global Template'),
                'link' => route('admin.settings.notification.services', ['service' => 'global-template']),
                'icon' => 'ph ph-globe',
            ],
            [
                'title' => __('Email Settings'),
                'link' => route('admin.settings.notification.services', ['service' => 'mail']),
                'icon' => 'ph ph-envelope',
            ],
            [
                'title' => __('SMS Settings'),
                'link' => route('admin.settings.notification.services', ['service' => 'sms']),
                'icon' => 'ph ph-chat',
            ],
            [
                'title' => __('Broadcast Notification Settings'),
                'link' => route('admin.settings.notification.services', ['service' => 'push']),
                'icon' => 'ph ph-bell-simple-ringing',
            ],
            [
                'title' => __('Template'),
                'icon' => 'ph ph-bell',
                'link' => route('admin.settings.notification.services', ['service' => 'template']),
            ],
        ];

        if ($service == 'sms') {
            return view('admin.pages.settings.notifications.index', ['service' => $service, 'buttons' => $buttons]);
        }

        if ($service == 'email') {
            return view('admin.pages.settings.notifications.index', ['service' => $service, 'buttons' => $buttons]);
        }

        if ($service == 'push') {
            return view('admin.pages.settings.notifications.index', ['service' => $service, 'buttons' => $buttons]);
        }

        if ($service == 'template') {
            $templates = ModalIndexQuey::get(model: NotificationTemplate::query()->where('type', '!=', NotificationType::DEFAULT->value));

            $template_buttons = [
                [
                    'label' => __('Add New Template'),
                    'icon' => 'ph ph-plus-bold',
                    'type' => 'link',
                    'link' => route('admin.settings.notification.templates.create'),
                ],
            ];

            $columns = [
                [
                    'label' => __('Name'),
                    'key' => 'name',
                    'is_sortable' => true,
                ],
                [
                    'label' => __('Subject'),
                    'key' => 'subject',
                    'is_sortable' => true,
                ],
                [
                    'label' => __('Status'),
                    'key' => 'status',
                    'is_sortable' => true,
                    'render' => function ($template) {
                        return '<span class="status '.($template->status == 'active' ? 'success' : 'danger').'">'.$template->status.'</span>';
                    },
                ],
                [
                    'label' => __('Action'),
                    'render' => function ($template) {
                        $action_buttons = [
                            [
                                'label' => __('Edit'),
                                'icon' => 'ph ph-pencil',
                                'type' => 'link',
                                'href' => route('admin.settings.notification.templates.edit', $template->id),
                            ],
                        ];

                        return view('admin.components.table-action', compact('action_buttons'))->render();
                    },
                ],
            ];

            return view('admin.pages.settings.notifications.index', compact('buttons', 'template_buttons', 'service', 'templates', 'columns'));
        }

        $defaultTemplate = NotificationTemplate::with('bodies')->default()->where('status', 'active')->first();

        return view('admin.pages.settings.notifications.index', ['service' => $service, 'buttons' => $buttons, 'defaultTemplate' => $defaultTemplate]);
    }

    public function store(Request $request, $service)
    {
        adminUserHasPermission(permission: 'edit');
        if ($service == 'sms') {

            $validated = $request->validate([
                'driver' => 'required|in:twilio,nexmo',
                'account_sid' => 'required_if:driver,twilio',
                'auth_token' => 'required_if:driver,twilio',
                'from' => 'required',
                'api_key' => 'required_if:driver,nexmo',
                'api_secret' => 'required_if:driver,nexmo',
            ]);

            $data = [];

            switch ($validated['driver']) {
                case 'twilio':
                    $data = [
                        'driver' => 'twilio',
                        'account_sid' => $validated['account_sid'],
                        'auth_token' => $validated['auth_token'],
                        'from' => $validated['from'],
                    ];
                    break;
                case 'nexmo':
                    $data = [
                        'driver' => 'nexmo',
                        'api_key' => $validated['api_key'],
                        'api_secret' => $validated['api_secret'],
                        'from' => $validated['from'],
                    ];
                    break;
            }

            storeOption([
                'sms_config' => $data,
            ]);

            return response()->json(['message' => __('Settings updated successfully'), 'reload' => true]);
        }

        if ($service == 'broadcast') {

            $validated = $request->validate([
                // firebase cloud messaging
                'apiKey' => 'required',
                'authDomain' => 'required',
                'projectId' => 'required',
                'storageBucket' => 'required',
                'messagingSenderId' => 'required',
                'appId' => 'required',
                'measurementId' => 'required',
                'vapidKey' => 'required',

                // firebase admin sdk
                'type' => 'required|in:service_account',
                'project_id' => 'required_if:type,service_account',
                'private_key_id' => 'required_if:type,service_account',
                'private_key' => 'required_if:type,service_account',
                'client_email' => 'required_if:type,service_account',
                'client_id' => 'required_if:type,service_account',
                'auth_uri' => 'required_if:type,service_account',
                'token_uri' => 'required_if:type,service_account',
                'auth_provider_x509_cert_url' => 'required_if:type,service_account',
                'client_x509_cert_url' => 'required_if:type,service_account',
                'universe_domain' => 'required',
            ]);

            $clientData = [
                'apiKey' => $validated['apiKey'],
                'authDomain' => $validated['authDomain'],
                'projectId' => $validated['projectId'],
                'storageBucket' => $validated['storageBucket'],
                'messagingSenderId' => $validated['messagingSenderId'],
                'appId' => $validated['appId'],
                'measurementId' => $validated['measurementId'],
                'vapidKey' => $validated['vapidKey'],
            ];

            $adminData = [
                'type' => $validated['type'],
                'project_id' => $validated['project_id'],
                'private_key_id' => $validated['private_key_id'],
                'private_key' => $validated['private_key'],
                'client_email' => $validated['client_email'],
                'client_id' => $validated['client_id'],
                'auth_uri' => $validated['auth_uri'],
                'token_uri' => $validated['token_uri'],
                'auth_provider_x509_cert_url' => $validated['auth_provider_x509_cert_url'],
                'client_x509_cert_url' => $validated['client_x509_cert_url'],
                'universe_domain' => $validated['universe_domain'],
            ];

            $storage = Storage::disk('firebase');

            $storage->put('cloud-messaging.json', json_encode($clientData));
            $storage->put('admin-sdk.json', json_encode($adminData));

            return response()->json(['message' => __('Settings updated successfully'), 'reload' => true]);
        }
        // email service
        $validated = $request->validate([
            // smtp
            'mailer' => 'required|in:smtp,mailgun,sendgrid,mailjet',
            'host' => 'required_if:mailer,smtp',
            'port' => 'required_if:mailer,smtp',
            'encryption' => 'required_if:mailer,smtp',
            'username' => 'required_if:mailer,smtp',
            'password' => 'required_if:mailer,smtp',
            // mailgun
            'domain' => 'required_if:mailer,mailgun',
            'secret' => 'required_if:mailer,mailgun',
            'endpoint' => 'required_if:mailer,mailgun',

            'mail_address' => 'required',
            'mail_name' => 'required',
        ]);

        $data = [];

        if ($validated['mailer'] == 'smtp') {
            $data = [
                'mailer' => $validated['mailer'],
                'host' => $validated['host'],
                'port' => $validated['port'],
                'encryption' => $validated['encryption'],
                'username' => $validated['username'],
                'password' => $validated['password'],
                'mail_address' => $validated['mail_address'],
                'mail_name' => $validated['mail_name'],
            ];
        }

        if ($validated['mailer'] == 'mailgun') {
            $data = [
                'mailer' => $validated['mailer'],
                'domain' => $validated['domain'],
                'secret' => $validated['secret'],
                'endpoint' => $validated['endpoint'],
                'mail_address' => $validated['mail_address'],
                'mail_name' => $validated['mail_name'],
            ];
        }

        storeOption([
            'email_config' => $data,
        ]);

        return response()->json(['message' => __('Settings updated successfully'), 'reload' => true]);
    }

    public function testEmailService(Request $request)
    {
        $validated = $request->validate([
            'send_to' => 'required|email',
            'subject' => 'required',
            'message' => 'required',
        ]);

        try {
            Mail::raw($validated['message'], function ($message) use ($validated) {
                $message->to($validated['send_to'])
                    ->subject($validated['subject']);
            });

            return response()->json(['message' => __('Email sent successfully')]);
        } catch (\Throwable $th) {
            return response()->json(['message' => $th->getMessage()]);
        }
    }

    public function testSmsService(Request $request)
    {
        $validated = $request->validate([
            'send_to' => 'required',
            'message' => 'required',
        ]);

        try {

            $smsService = resolve(SmsInterface::class);
            $smsService->send($validated['send_to'], $validated['message']);

            return response()->json(['message' => __('SMS sent successfully')]);
        } catch (\Throwable $th) {
            return response()->json(['message' => $th->getMessage()], 400);
        }
    }

    public function uploadFirebaseJson(Request $request, $type, JsonHelper $json_helper)
    {
        $request->validate([
            'file' => 'required|mimes:json',
        ]);

        $file = $request->file('file');

        if (! $json_helper->checkValidJson($file)) {
            return response()->json(['message' => __('Invalid JSON file')], 400);
        }

        $storage = Storage::disk('firebase');

        if ($type == 'client') {
            $storage->put('cloud-messaging.json', file_get_contents($file));
        } else {
            $storage->put('admin-sdk.json', file_get_contents($file));
        }

        return response()->json(['reload' => true, 'message' => __('JSON file uploaded successfully')]);
    }

    public function downloadFirebaseJson($type)
    {
        $storage = Storage::disk('firebase');

        $file = $storage->get($type == 'client' ? 'cloud-messaging.json' : 'admin-sdk.json');

        return Response::make($file, 200, [
            'Content-Type' => 'application/json',
            'Content-Disposition' => 'attachment; filename="'.$type.'.json"',
        ]);
    }

    public function testFirebaseService(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required',
            'message' => 'required',
        ]);

        $firebase = new FirebaseNotificationService;

        $client = User::first();

        try {
            $firebase->sendNotification(
                $validated['title'],
                $validated['message'],
                $client->fcm_token ?? '',
            );

            Notification::create([
                'type' => NotifyEventType::NEW_USER,
                'notifiable_id' => $client->id,
                'notifiable_type' => User::class,
                'data' => $validated['message'],
            ]);

        } catch (\Throwable $th) {
            return response()->json(['message' => $th->getMessage()], 400);
        }

        return response()->json(['message' => __('Notification sent successfully')]);
    }

    public function tokenUpdate(Request $request)
    {
        $request->validate([
            'token' => 'required|string',
        ]);

        try {
            /**
             * @var \App\Models\Admin $user
             */
            $user = auth('admin')->user();

            $user->fcm_token = $request->token;
            $user->save();

            return response()->json(['success' => true]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => __('Failed to subscribe to topic')], 500);
        }
    }
}
