<?php

namespace Mtc\Plugins\Clinic\Providers;

use App\Events\AssessmentCreatedEvent;
use App\Events\AssessmentInitEvent;
use App\Events\MemberCreatedEvent;
use App\Events\OrderCreatedEvent;
use App\Events\OrderRefundedEvent;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
use Mtc\Modules\Members\Classes\Events\SavedMember;
use Mtc\Modules\Members\Models\Member;
use Mtc\Modules\Members\Models\MemberAttribute;
use Mtc\Modules\Members\Models\MemberNote;
use Mtc\Plugins\Clinic\Src\Clinic;
use Mtc\Plugins\Clinic\Src\Console\Commands\SendReviewInvitationsCommand;
use Mtc\Plugins\Clinic\Src\Models\BpTrack;
use Mtc\Plugins\Clinic\Src\Models\Review;
use Mtc\Plugins\Clinic\Src\Models\Treatment;
use Mtc\Plugins\Clinic\Src\Models\WeightTrack;
use Mtc\Shop\Assessment\Assessment;
use Mtc\Shop\Events\OrderPaidEvent;
use Mtc\Shop\Events\OrderStatusChangedEvent;
use Mtc\Shop\Item;
use Mtc\Shop\Order;

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

        if (config('app.env') === 'production') {
            App::make(Schedule::class)
                ->command('clinic:reviews-invite')
                ->dailyAt('09:00');
        }
    }

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

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

    /**
     * Register events
     *
     * @return void
     */
    protected function registerEvents(): void
    {
        Event::listen(OrderPaidEvent::class, function (OrderPaidEvent $event): void {
            Clinic::logOrderPaidEvent($event);
        });
        Event::listen(OrderCreatedEvent::class, function (OrderCreatedEvent $event): void {
            Clinic::logOrderCreatedEvent($event);
        });
        Event::listen(OrderStatusChangedEvent::class, function (OrderStatusChangedEvent $event): void {
            Clinic::logOrderStatusUpdateEvent($event);
        });
        Event::listen(OrderRefundedEvent::class, function (OrderRefundedEvent $event): void {
            Clinic::logOrderRefundEvent($event);
        });
        Event::listen(MemberCreatedEvent::class, function (MemberCreatedEvent $event): void {
            Clinic::logMemberCreatedEvent($event);
        });
        Event::listen(AssessmentCreatedEvent::class, function (AssessmentCreatedEvent $event): void {
            Clinic::processCreatedAssessment($event);
        });
        Event::listen(AssessmentInitEvent::class, function (AssessmentInitEvent $event): void {
            Clinic::processInitAssessment($event);
        });
        Event::listen(SavedMember::class, function (SavedMember $event): void {
            Clinic::processMemberSaved($event);
        });
    }

    /**
     * Register dynamic relationships
     *
     * @return void
     */
    protected function registerRelationships(): void
    {
        Member::resolveRelationUsing('attributes', function ($memberModel) {
            return $memberModel->hasMany(MemberAttribute::class, 'member_id');
        });
        Member::resolveRelationUsing('treatments', function ($memberModel) {
            return $memberModel->hasMany(Treatment::class, 'member_id');
        });
        Member::resolveRelationUsing('weightTrack', function ($memberModel) {
            return $memberModel->hasMany(WeightTrack::class, 'member_id');
        });
        Member::resolveRelationUsing('bpTrack', function ($memberModel) {
            return $memberModel->hasMany(BpTrack::class, 'member_id');
        });
        Item::resolveRelationUsing('treatments', function ($itemModel) {
            return $itemModel->hasMany(Treatment::class, 'item_id');
        });
        MemberNote::resolveRelationUsing('review', function ($memberNoteModel) {
            return $memberNoteModel->belongsTo(Review::class, 'review_id');
        });
        Order::resolveRelationUsing('review', function ($orderModel) {
            return $orderModel->belongsTo(Review::class, 'review_id');
        });
        Assessment::resolveRelationUsing('review', function ($assessmentModel) {
            return $assessmentModel->belongsTo(Review::class, 'review_id');
        });
    }
}
