<?php

namespace Mtc\Plugins\Clinic\Src\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\HigherOrderBuilderProxy;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Mtc\Core\Admin\User;
use Mtc\Core\AdminUser;
use Mtc\Modules\Members\Models\Member;
use Mtc\Plugins\Clinic\Src\Clinic;
use Mtc\Plugins\Clinic\Src\Logger;
use Mtc\Plugins\Clinic\Src\Uploader;
use Mtc\Shop\Assessment\Assessment;
use Mtc\Shop\Assessment\Question;

/**
 * Accessors
 *
 * @property int $id
 * @property int $member_id
 * @property int $file_id
 * @property int $review_id
 * @property int $high
 * @property int $low
 * @property int $heart_rate
 * @property string $date_provided
 *
 * @property Carbon $created_at
 * @property Carbon $updated_at
 *
 * @property Member $member
 * @property AdminUser $user
 * @property Review $review
 * @property PatientFile|null $file
 */
class BpTrack extends Model
{
    protected $table = 'patient_bp_track';

    protected $fillable = [
        'member_id',
        'file_id',
        'review_id',
        'high',
        'low',
        'heart_rate',
        'date_provided',
    ];

    /**
     * @return BelongsTo
     */
    public function member(): BelongsTo
    {
        return $this->belongsTo(Member::class, 'member_id');
    }

    /**
     * @return BelongsTo
     */
    public function file(): BelongsTo
    {
        return $this->belongsTo(PatientFile::class, 'file_id');
    }

    /**
     * @return BelongsTo
     */
    public function review(): BelongsTo
    {
        return $this->belongsTo(Review::class, 'review_id');
    }

    /**
     * Simple validator
     *
     * @param array $input
     * @return array
     */
    public static function validate(array $input): array
    {
        $required = [
            'low',
            'high',
            'heart_rate',
            'date_provided',
        ];

        $errors = [];

        foreach ($required as $field) {
            if (empty($input[$field])) {
                $errors[$field] = 'This field is required';
            }
        }

        return $errors;
    }

    /**
     * Uploads BP file from request
     *
     * @param $requestFile
     * @param $data
     * @return HigherOrderBuilderProxy|JsonResponse|mixed
     */
    public static function uploadFile($requestFile, $data): mixed
    {
        /** @var Member $member */
        $member = Member::query()
            ->with('addressBilling')
            ->find($data['member_id']);
        $uploadParams = [
            'public' => false,
            'allowed_formats' => PatientFile::IMAGE_EXTENSIONS,
            'type' => PatientFile::FILE_TYPE_BP_TRACK,
            'title' => 'BP Readings ' .
                $member->addressBilling->firstname . ' ' . $member->addressBilling->lastname,
        ];
        $uploader = new Uploader($uploadParams);
        if (!$file = $uploader->uploadFile($requestFile)) {
            return response()->json([
                'errors' => [
                    'file' => implode(', ', $uploader->errors),
                ],
            ]);
        }
        $file->update([
            'member_id' => $member->id,
            'date_provided' => $data['date_provided'],
        ]);

        return $file;
    }

    /**
     * Checks if the assessment has BP related answers and store them
     *
     * @param Assessment $assessment
     * @param array $uploadedFiles
     * @return void
     */
    public static function checkAndStoreFromAssessment(Assessment $assessment, array $uploadedFiles): void
    {
        if (empty($assessment->member_id)) {
            // No member to store BP readings against
            return;
        }
        $assessment->refresh();
        $bpAnswers = $assessment->answers()
            ->with('question')
            ->whereHas('question', function (Builder $query) {
                $query->where('question_type', Question::TYPE_BP_READINGS)
                    ->orWhere('subtype', Question::TYPE_BP_IMAGE);
            })
            ->get();

        if ($bpAnswers->count() === 0) {
            return;
        }

        $bpTrack = [
            'member_id' => $assessment->member_id,
            'review_id' => $assessment->review_id,
            'date_provided' => $assessment->created_at->format('Y-m-d'),
        ];
        foreach ($bpAnswers as $bpAnswer) {
            if ($bpAnswer->question->question_type === Question::TYPE_BP_READINGS) {
                $bpData = (array)json_decode($bpAnswer->answer)->values;
                $bpTrack = array_merge($bpTrack, $bpData);
                continue;
            }

            if ($bpAnswer->question->subtype === Question::TYPE_BP_IMAGE) {
                if (empty($uploadedFiles[$bpAnswer->question_id])) {
                    continue;
                }
                $uploadedFile = $uploadedFiles[$bpAnswer->question_id];
                $file = BpTrack::uploadFile($uploadedFile, [
                    'date_provided' => $assessment->created_at,
                    'member_id' => $assessment->member_id,
                ]);
                $bpTrack['file_id'] = $file->id;
                (new Logger($file, Clinic::getActor(), $file->id))
                    ->log(Logger::FILE, Logger::ACTION_CREATED, $file->toArray());
            }
        }

        $bpTrack = BpTrack::query()
            ->create($bpTrack);

        (new Logger($bpTrack, Clinic::getActor(), $assessment->member_id))
            ->log(Logger::BP_TRACK, Logger::ACTION_CREATED, $bpTrack->toArray());
    }
}