<?php

namespace Mtc\Plugins\Wisebee\Providers;

use App\Admin\OrdersHelper;
use App\Events\AdminUserCreatedEvent;
use App\Events\AssessmentInitEvent;
use App\Events\BasketItemsLoadedEvent;
use App\Events\BasketLoadedEvent;
use App\Events\BasketRemoveItemEvent;
use App\Events\MemberCreatedEvent;
use App\Events\MemberUpdatedEvent;
use App\Events\OrderCreatedEvent;
use App\Events\OrderRefundedEvent;
use App\Events\OrderRowPrintedEvent;
use App\Events\OrderTabNavPrintedEvent;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
use Mtc\Core\AdminUser;
use Mtc\Modules\Members\Classes\Events\SavedMember;
use Mtc\Modules\Members\Models\Member;
use Mtc\Plugins\Wisebee\Classes\Commands\PullParticipantHashCommand;
use Mtc\Plugins\Wisebee\Classes\Events\WisebeeWebhookEvent;
use Mtc\Plugins\Wisebee\Classes\Handlers\BaseHandler;
use Mtc\Plugins\Wisebee\Classes\Handlers\CustomerNoteHandler;
use Mtc\Plugins\Wisebee\Classes\Handlers\UserHandler;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeCategory;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeConsultation;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeMember;
use Mtc\Plugins\Wisebee\Classes\Models\WisebeeUser;
use Mtc\Plugins\Wisebee\Classes\WisebeeManager;
use Mtc\Shop\Admin\ViewHelper;
use Mtc\Shop\Category;
use Mtc\Shop\Events\MemberNoteCreatedEvent;
use Mtc\Shop\Events\OrderPaidEvent;
use Mtc\Shop\Item;
use Mtc\Shop\Order;

class WisebeeServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->commands([
            PullParticipantHashCommand::class,
        ]);
    }

    /**
     * Registers Wisebee
     *
     * @return void
     */
    public function register(): void
    {
        $this->loadRoutesFrom(__DIR__.'/../routes/wisebee.php');
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
        $this->mergeConfigFrom(__DIR__.'/../config/wisebee.php', 'wisebee');

        if (! config('wisebee.enabled')) {
            return;
        }
        $this->registerEvents();
        $this->registerRelationships();
    }

    /**
     * Register events
     *
     * @return void
     */
    protected function registerEvents(): void
    {
        Event::listen(WisebeeWebhookEvent::class, function ($event): void {
            $post = $event->getPost();
            $handler = new BaseHandler(new WisebeeManager);
            $handler->processWebhookCall($post);
        });

        // Listen to basket remove item and cancel the consultation in WISEBEE
        Event::listen(BasketRemoveItemEvent::class, function ($event): void {
            $wisebeeManager = new WisebeeManager;
            $wisebeeManager->deleteBasketConsultation($event->getBasketItemId());
        });

        // Listen to basket remove item and cancel the consultation in WISEBEE
        Event::listen(BasketLoadedEvent::class, function (BasketLoadedEvent $event): void {
            $basket = $event->getBasket();
            WisebeeManager::processBasket($basket);
        });

        // Listen to basket remove item and cancel the consultation in WISEBEE
        Event::listen(BasketItemsLoadedEvent::class, function (BasketItemsLoadedEvent $event): void {
            $basket = $event->getBasket();
            WisebeeManager::processBasketItems($basket);
        });

        // Listen to basket remove item and cancel the consultation in WISEBEE
        Event::listen(OrderCreatedEvent::class, function (OrderCreatedEvent $event): void {
            WisebeeManager::processNewOrder($event->getOrder(), $event->getBasket());
        });

        // When order is paid, check for consultations in the order
        Event::listen(OrderPaidEvent::class, function (OrderPaidEvent $event): void {
            $wisebeeManager = new WisebeeManager;
            $wisebeeManager->processOrderPaid($event);
        });

        // When order is refunded, create refund transactions
        Event::listen(OrderRefundedEvent::class, function (OrderRefundedEvent $event): void {
            $wisebeeManager = new WisebeeManager;
            $wisebeeManager->processOrderRefunded($event);
        });
        Event::listen(MemberCreatedEvent::class, function (MemberCreatedEvent $event): void {
            $wisebeeManager = new WisebeeManager;
            $wisebeeManager->syncMember($event);
        });
        Event::listen(MemberUpdatedEvent::class, function (MemberUpdatedEvent $event): void {
            $wisebeeManager = new WisebeeManager;
            $wisebeeManager->syncMember($event);
        });

        // When order note is created, we push it to Wisebee
        Event::listen(MemberNoteCreatedEvent::class, function (MemberNoteCreatedEvent $event): void {
            $handler = new CustomerNoteHandler(new WisebeeManager);
            $handler->createNoteInWisebee($event->note);
        });

        // Checks and creates user in Wisebee if it doesn't exist
        Event::listen(AdminUserCreatedEvent::class, function (AdminUserCreatedEvent $event): void {
            $handler = new UserHandler(new WisebeeManager);
            $handler->handleAdminCreated($event->userID);
        });

        // Checks and creates user in Wisebee if it doesn't exist
        Event::listen(OrderTabNavPrintedEvent::class, function (OrderTabNavPrintedEvent $event): void {
            $ordersHelper = new OrdersHelper([
                'product_type' => Item::TYPE_CONSULTATION,
            ]);
            $orderCount = $ordersHelper
                ->getOrdersBuilderQuery()
                ->get()
                ->count();

            echo
                template('wisebee/orderTabNav.twig', [
                    'selected' => request()->input('product_type') === Item::TYPE_CONSULTATION,
                    'orderCount' => $orderCount,
                ])
            ;
        });

        // Checks and creates user in Wisebee if it doesn't exist
        Event::listen(OrderRowPrintedEvent::class, function (OrderRowPrintedEvent $event): void {
            if (request()->input('product_type') !== Item::TYPE_CONSULTATION) {
                return;
            }

            if ($event->rowType === ViewHelper::HEADER_ROW) {
                echo template('wisebee/orderHeaderCell.twig');

                return;
            }

            if (empty($event->order)) {
                return;
            }

            $orderDocuments = null;

            $order = $event->order->eloquent();
            /** @var Order\Item $orderItem */
            foreach ($order->items as $orderItem) {
                $item = $orderItem->item;
                if (empty($item) || empty($item->wisebee_consultation)) {
                    continue;
                }
                if (empty($orderDocuments)) {
                    $orderDocuments = $item->wisebee_consultation->documents;
                }
                $orderDocuments = $orderDocuments->merge($item->wisebee_consultation->documents);
            }

            ;

            $role = $event->role;

            echo
                template('wisebee/orderRowCell.twig', [
                    'role' => $role,
                    'order' => $order,
                    'documents' => $orderDocuments,
                ])
            ;
        });

        // Checks and creates user in Wisebee if it doesn't exist
        Event::listen(AssessmentInitEvent::class, function (AssessmentInitEvent $event): void {
            WisebeeCategory::checkAndRedirectFromAssessment($event->getRequest()->all());
        });
    }

    /**
     * Register dynamic relationships
     *
     * @return void
     */
    protected function registerRelationships(): void
    {
        Member::resolveRelationUsing('wisebee_member', function ($memberModel) {
            return $memberModel->hasOne(WisebeeMember::class, 'member_id');
        });

        Item::resolveRelationUsing('wisebee_consultation', function ($itemModel) {
            return $itemModel->hasOne(WisebeeConsultation::class, 'item_id');
        });

        AdminUser::resolveRelationUsing('wisebee_user', function ($adminUserModel) {
            return $adminUserModel->hasOne(WisebeeUser::class, 'admin_user_id');
        });

        Category::resolveRelationUsing('wisebee_categories', function ($categoryModel) {
            return $categoryModel->hasMany(WisebeeCategory::class, 'category_id');
        });
    }
}
