<?php
namespace Mtc\Shop\Assessment;

use App\Casts\OptionalEncrypted;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\belongsTo;
use Mtc\Modules\DoctorSurgery\Classes\DoctorSurgery;
use Mtc\Modules\Members\Models\Member;
use Mtc\Shop\Item;
use Mtc\Shop\Order;

/**
 * @author Uldis Zvirbulis <uldis.zvirbulis@mtcmedia.co.uk>
 */
class Answer extends Model
{
    protected $table = 'assessment_answers';

    protected $fillable = [
        'form_id',
        'question_id',
        'member_id',
        'order_id',
        'item_id',
        'answer',
        'answer_change_count',
        'answer_confirmed',
        'answer_changed_after_confirmation',
    ];

    protected $casts = [
        'answer' => OptionalEncrypted::class,
    ];

    /**
     * Define the relationship to Form
     * @return belongsTo
     */
    public function form(): belongsTo
    {
        return $this->belongsTo(Form::class, 'form_id');
    }

    /**
     * Define the relationship to Question
     * @return belongsTo
     */
    public function question(): belongsTo
    {
        return $this->belongsTo(Question::class, 'question_id');
    }

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

    /**
     * Define the relationship to Order
     * @return belongsTo
     */
    public function order(): belongsTo
    {
        return $this->belongsTo(Order::class, 'order_id');
    }

    /**
     * Define the relationship to Item
     * @return belongsTo
     */
    public function item(): belongsTo
    {
        return $this->belongsTo(Item::class, 'item_id');
    }

    /**
     * Define the relationship to Assessment
     * @return belongsTo
     */
    public function assessment(): belongsTo
    {
        return $this->belongsTo(Assessment::class, 'assessment_id');
    }

    /**
     * Gets the restriction level of answer:
     * 0 - no restriction
     * 1 - alert
     * 2 - block
     * 3 - okay
     *
     * @return integer
     */

    public function answerRestrictionLevel(): int
    {
        $block_if_answers = empty($this->question->block_if) ? [] : (array) json_decode($this->question->block_if, false);
        $okay_if_answers = empty($this->question->okay_if) ? [] : (array) json_decode($this->question->okay_if, false);
        $alert_if_answers = empty($this->question->alert_if) ? [] : (array) json_decode($this->question->alert_if, false);
        if ($this->question->is_multiple) {
            $answers = (array) json_decode($this->answer, true);
            // First locate if there's any blockers
            foreach ($answers as $answer_option) {
                if (!empty($this->question->block_if) && in_array($answer_option, $block_if_answers)) {
                    return 2;
                }
            }
            // Then look for alerts
            foreach ($answers as $answer_option) {
                if (!empty($this->question->alert_if) && in_array($answer_option, $alert_if_answers)) {
                    return 1;
                }
            }
            // Look for Okay
            foreach ($answers as $answer_option) {
                if (!empty($this->question->okay_if) && in_array($answer_option, $okay_if_answers)) {
                    return 3;
                }
            }
        } else {
            if ($this->question->question_type === 'notify_gp') {
                $gp_data = json_decode($this->answer);
                $answer_text = $gp_data->notify;
            } else {
                $answer_text = $this->answer;
            }
            if (!empty($this->question->block_if) && in_array($answer_text, $block_if_answers)) {
                return 2;
            }
            if (!empty($this->question->alert_if) && in_array($answer_text, $alert_if_answers)) {
                return 1;
            }
            if (!empty($this->question->okay_if) && in_array($answer_text, $okay_if_answers)) {
                return 3;
            }
        }

        return 0;
    }

    /**
     * Resolve answer text
     *
     * @return void
     */
    public function getDisplayAnswer(): void
    {
        if ($this->question->question_type === 'notify_gp') {

            $gp_data = json_decode($this->answer);

            $this->answer = "<div>{$this->message}</div>";

            if (empty($gp_data->id)) {
                return;
            }

            if (!$gp_data = DoctorSurgery::query()->find($gp_data->id)) {
                return;
            }

            $this->answer .= '<div class="gpTableAddress">';
            $this->answer .= 'Practice Name: ' . ucwords(strtolower($gp_data->practice_name)) . '<br />';
            $this->answer .= 'City: ' . ucwords(strtolower($gp_data->city)) . '<br />';
            $this->answer .= 'Address 1: ' . ucwords(strtolower($gp_data->address_1)) . '<br />';
            $this->answer .= 'Address 2: ' . ucwords(strtolower($gp_data->address_2)) . '<br />';
            $this->answer .= 'Postcode: ' . $gp_data->postcode . '<br />';
            $this->answer .= 'Phone: ' . $gp_data->phone . '<br />';
            $this->answer .= '</div>';
            return;
        }

        if ($this->question->is_multiple) {
            $this->answer = implode('<br />', (array) json_decode($this->answer, true));
            return;
        }
        if ($this->question && $this->question->expectsFile()) {
            $downloadLink = '/shop/admin/assessment/view_image.php?id=' . $this->id;
            $this->answer = "<a href='{$downloadLink}' target='_blank'>View Image</a>";
            return;
        }

        $this->answer = match ($this->question->question_type) {
            'yes' => 'I agree, confirm and consent',
            default => clean_page($this->answer),
        };
    }

    /**
     * Get answer details for display
     *
     * @return void
     */
    public function getDetails(): void
    {
        $this->answerColour = '';
        if ($this->answer_confirmed) {
            $this->answerColour = $this->answer_changed_after_confirmation % 2 == 0 ? 'redBG' : 'yellowBG';
        }
        $this->restriction_level = $this->answerRestrictionLevel();
        $this->rowClass = '';
        $this->message = '';
        if ($this->restriction_level === 1) {
            $this->rowClass = 'rowAlert';
            $this->message = 'Alert!';
        } elseif ($this->restriction_level === 2) {
            $this->rowClass = 'rowBlock';
            $this->message = 'Block!';
        } elseif ($this->restriction_level === 3) {
            $this->rowClass = 'rowOkay';
            $this->message = 'Okay!';
        }

        $this->question->question_text = str_replace('<p>&nbsp;</p>', '', $this->question->question_text);

        $this->interactions = [];
        if ($this->question->question_type === 'medications' && $this->assessment->orderItems->count() > 0) {
            $orderItem = $this->assessment->orderItems[0];
            $item = $orderItem->item;
            $this->interactions = $item->incompatible_medications()
                ->where(function ($query) {
                    collect(explode(',', $this->answer))
                        ->each(function ($term) use ($query) {
                            $query->orWhere('medication', 'like', $term);
                        });
                })
                ->get();
        }

        if (
            in_array($this->question->question_type, [
                Question::TYPE_BMI,
                Question::TYPE_BP_READINGS,
            ])
        ) {
            $answer = json_decode($this->answer);
            $this->answer = '';
            if ($this->question->question_type === Question::TYPE_BMI) {
                $this->answer .= '<strong>BMI: ' . $answer->bmi->value . '</strong><br />';
                if (!empty($answer->bmi->type)) {
                    if (strtolower($answer->bmi->type) === 'metric') {
                        $this->answer .= 'Weight: ' . $answer->bmi->metric->weight_kg . 'kg<br />';
                        $this->answer .= 'Height: ' . $answer->bmi->metric->height_cm . 'cm<br />';
                    } elseif (strtolower($answer->bmi->type) === 'imperial') {
                        $this->answer .= 'Weight: ' . $answer->bmi->imperial->weight_stone . 'st ' . $answer->bmi->imperial->weight_pounds . 'lb<br />';
                        $this->answer .= 'Height: ' . $answer->bmi->imperial->height_feet . 'ft ' . $answer->bmi->imperial->height_inches . 'in<br />';
                    }

                    if (!empty($answer->bmi->ethnicity)) {
                        $this->answer .= 'Ethnicity: ' . $answer->bmi->ethnicity->name . '<br />';

                        if (!empty($answer->bmi->ethnicity->category)) {
                            $this->answer .= 'Category: ' . $answer->bmi->ethnicity->category . '<br />';
                        }
                    }
                }
            }
            if ($this->question->question_type === Question::TYPE_BP_READINGS) {
                if (!empty($answer->values)) {
                    $this->answer .= 'Low: ' . $answer->values->low . '<br />';
                    $this->answer .= 'High: ' . $answer->values->high . '<br />';
                    $this->answer .= 'Heart Rate: ' . $answer->values->heart_rate . '<br />';
                }
            }
        }

        if (!in_array($this->question->question_type, ['yes_no', 'yes'])) {
            $this->answer_change_count = 'N/A';
        }
    }

}
