<?php

namespace Mtc\Plugins\Clinic\Src;

use App\Events\AssessmentCreatedEvent;
use App\Events\AssessmentInitEvent;
use App\Events\MemberCreatedEvent;
use App\Events\OrderCreatedEvent;
use App\Events\OrderRefundedEvent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Mtc\Core\Admin\Menu;
use Mtc\Core\Admin\User;
use Mtc\Modules\Members\Classes\Auth;
use Mtc\Modules\Members\Classes\Events\SavedMember;
use Mtc\Plugins\Clinic\Src\Models\BpTrack;
use Mtc\Plugins\Clinic\Src\Models\PatientFile;
use Mtc\Plugins\Clinic\Src\Models\Review;
use Mtc\Plugins\Clinic\Src\Models\WeightTrack;
use Mtc\Shop\Events\OrderPaidEvent;
use Mtc\Shop\Events\OrderStatusChangedEvent;

class Clinic
{
    const MENU_CLINIC = 'Clinic';

    /**
     * Initializes the plugin
     *
     * @return void
     */
    public static function init(): void
    {
        self::injectAdminMenuItems();
    }


    /**
     * Injects menu items in admin menu
     *
     * @return void
     */
    protected static function injectAdminMenuItems(): void
    {
        if (Menu::query()->where('title', self::MENU_CLINIC)->exists()) {
            return;
        }
        $menuClinic = Menu::query()
            ->create([
                'sub_id' => '0',
                'title' => self::MENU_CLINIC,
                'icon' => '',
                'order' => '2',
            ]);

        $subItems = [
            [
                'sub_id' => $menuClinic->id,
                'title' => 'Dashboard',
                'path' => route('admin-dashboard', [], false),
                'activePath' => route('admin-dashboard', [], false),
                'icon' => 'fa fa-medkit',
                'order' => '0',
            ],
            [
                'sub_id' => $menuClinic->id,
                'title' => 'View Patients',
                'path' => route('admin-patients', [], false),
                'activePath' => route('admin-patients', [], false),
                'icon' => 'fa fa-user-md',
                'order' => '1',
            ],
            [
                'sub_id' => $menuClinic->id,
                'title' => 'Reviews',
                'path' => route('admin-reviews', [], false),
                'activePath' => route('admin-reviews', [], false),
                'icon' => 'fa fa-check-square',
                'order' => '2',
            ],
            [
                'sub_id' => $menuClinic->id,
                'title' => 'Assessment Forms',
                'path' => '/shop/admin/assessment/manage.forms.php',
                'activePath' => '/shop/admin/assessment/',
                'icon' => 'fa fa-list-alt',
                'order' => '3',
            ],
            [
                'sub_id' => $menuClinic->id,
                'title' => 'Review Types',
                'path' => route('admin-review-types', [], false),
                'activePath' => route('admin-review-types', [], false),
                'icon' => 'fa fa-cog',
                'order' => '4',
            ],
            [
                'sub_id' => $menuClinic->id,
                'title' => 'Medications',
                'path' => '/shop/admin/medications/manage.medications.php',
                'activePath' => '/shop/admin/medications/',
                'constant' => '',
                'icon' => 'fa fa-cubes',
                'new_window' => '0',
                'order' => '10',
            ],
            [
                'sub_id' => $menuClinic->id,
                'title' => 'Medical Conditions',
                'path' => '/shop/admin/medical_conditions/manage.medical_conditions.php',
                'activePath' => '/shop/admin/medical_conditions/',
                'constant' => '',
                'icon' => 'fa fa-cubes',
                'new_window' => '0',
                'order' => '11',
            ],
        ];

        foreach ($subItems as $subItem) {
            Menu::query()
                ->create($subItem);
        }
    }

    /**
     * Get either logged in admin or logged in member
     *
     * @return Builder|Builder[]|Collection|Model
     */
    public static function getActor()
    {
        $adminUser = User::getAdminUser();
        return $adminUser ?: Auth::getLoggedInMember();
    }

    /**
     * Logs order paid event
     *
     * @param OrderCreatedEvent $event
     * @return void
     */
    public static function logOrderCreatedEvent(OrderCreatedEvent $event): void
    {
        $order = $event->getOrder();
        (new Logger($order, self::getActor(), $order->member))
            ->log(Logger::ORDER, Logger::ACTION_CREATED);
    }

    /**
     * Logs order paid event
     *
     * @param OrderPaidEvent $event
     * @return void
     */
    public static function logOrderPaidEvent(OrderPaidEvent $event): void
    {
        $order = $event->getOrder()->eloquent();
        (new Logger($order, self::getActor(), $order->member))
            ->log(Logger::ORDER, Logger::ACTION_PAID);
    }

    /**
     * Logs order status updated event
     *
     * @param OrderStatusChangedEvent $event
     * @return void
     */
    public static function logOrderStatusUpdateEvent(OrderStatusChangedEvent $event): void
    {
        $order = $event->getOrder();
        if (!$order->paid) {
            // Don't log order status change before it's paid.
            return;
        }
        (new Logger($order->eloquent(), User::getAdminUser(), $order->member))
            ->log(Logger::ORDER_STATUS, $event->getStatus());
    }

    /**
     * Logs order refund event
     *
     * @param OrderRefundedEvent $event
     * @return void
     */
    public static function logOrderRefundEvent(OrderRefundedEvent $event): void
    {
        $order = $event->getOrder()->eloquent();
        (new Logger($event->getOrder()->eloquent(), User::getAdminUser(), $order->member))
            ->log(Logger::REFUND, $event->getAmount());
    }

    /**
     * Logs order refund event
     *
     * @param MemberCreatedEvent $event
     * @return void
     */
    public static function logMemberCreatedEvent(MemberCreatedEvent $event): void
    {
        $member = $event->getMember();
        (new Logger($member, self::getActor(), $member->id))
            ->log(Logger::MEMBER, Logger::ACTION_CREATED);
    }

    /**
     * Any actions performed after an assessment has been created
     *
     * @param AssessmentCreatedEvent $event
     * @return void
     */
    public static function processCreatedAssessment(AssessmentCreatedEvent $event): void
    {
        $assessment = $event->getAssessment();
        $request = $event->getRequest();
        $uploadedFiles = $request->file('questions', []);

        Review::checkAndStoreFromAssessment($assessment, $request);
        BpTrack::checkAndStoreFromAssessment($assessment, $uploadedFiles);
        WeightTrack::checkAndStoreFromAssessment($assessment);
        PatientFile::checkAndStoreFromAssessment($uploadedFiles);
    }

    /**
     * Any actions performed before the assessment form is loaded
     *
     * @param AssessmentInitEvent $event
     * @return void
     */
    public static function processInitAssessment(AssessmentInitEvent $event): void
    {
        $request = $event->getRequest();

        Review::checkAndRedirectFromAssessment($request);
    }

    /**
     * Process member saved event
     *
     * @param SavedMember $event
     * @return void
     */
    public static function processMemberSaved(SavedMember $event): void
    {
        $oldMember = $event->member_manager->oldMember;
        $member = $event->member;

        // ID check has been marked as passed
        if (empty($oldMember->passed_id_check) && !empty($member->passed_id_check)) {
            (new Logger($member, self::getActor(), $member->id))
                ->log(Logger::PATIENT_ID, Logger::ACTION_CONFIRMED);
        }
    }
}