<?php
namespace Mtc\Shop\Assessment;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\belongsTo;
use Illuminate\Database\Eloquent\Relations\hasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Http\UploadedFile;
use stdClass;

/**
 * @author Uldis Zvirbulis <uldis.zvirbulis@mtcmedia.co.uk>
 *
 * Accessors
 *
 * @property array|null $recommended
 * @property array|null $excluded
 *
 */
class Question extends Model
{
    use SoftDeletes;
    protected $table = 'assessment_questions';

    protected $fillable = [
        'old_id',
        'form_id',
        'question_type',
        'subtype',
        'question_text',
        'variations',
        'clearall_answer',
        'is_multiple',
        'is_required',
        'alert_if',
        'block_if',
        'okay_if',
        'cant_proceed_if',
        'show_if_question',
        'show_if_answer',
        'recommended',
        'excluded',
        'answer_expires_after_days',
        'is_active',
        'sort',
        'settings',
    ];

    protected $casts = [
        'recommended' => 'array',
        'excluded' => 'array',
    ];

    public function getRecommendedAttribute($value): array
    {
        return $this->normalizeJsonField($value);
    }

    public function getExcludedAttribute($value): array
    {
        return $this->normalizeJsonField($value);
    }

    private function normalizeJsonField($value): array
    {
        // Defining a get accessor bypasses the 'array' cast, so we receive the raw DB string.
        // Some legacy rows were saved double-encoded (the array cast ran over an already-encoded
        // string), so decode repeatedly until we land on an array or run out of valid JSON.
        $iterations = 0;
        while (is_string($value) && $iterations < 3) {
            $decoded = json_decode($value, true);
            if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
                return [];
            }
            $value = $decoded;
            $iterations++;
        }
        return is_array($value) ? $value : [];
    }

    public static $file_question_types = [
        'image',
    ];

    public static $file_type_allowed_mimes = [
        'image' => [
            'image/jpeg',
            'image/png',
            'image/gif',
            'image/webp',
        ]
    ];

    const FILE_MAX_BYTES = 10 * 1024 * 1024;

    const TYPE_TEXT = 'text';
    const TYPE_TEXTAREA = 'textarea';
    const TYPE_HTML = 'html';
    const TYPE_DATE = 'date';
    const TYPE_YES_NO = 'yes_no';
    const TYPE_YES = 'yes';
    const TYPE_VARIATIONS = 'variations';
    const TYPE_SECTION = 'section';
    const TYPE_BMI = 'bmi';
    const TYPE_IMAGE = 'image';
    const TYPE_NOTIFY_GP = 'notify_gp';
    const TYPE_ALLERGIES = 'allergies';
    const TYPE_MEDICATIONS = 'medications';
    const TYPE_CONDITIONS = 'conditions';
    const TYPE_ALERT = 'alert';
    const TYPE_INFORMATION = 'information';
    const TYPE_INFORMATION_GREEN = 'information_green';
    const TYPE_NUMBER = 'number';
    const TYPE_EMAIL = 'email';
    const TYPE_WEIGHT = 'weight';
    const TYPE_BP_READINGS = 'bp_readings';
    const TYPE_BP_IMAGE = 'bp_image';
    const TYPE_ID_IMAGE = 'id_image';
    const TYPE_SELFIE_IMAGE = 'selfie_image';

    public static $question_types = [
        self::TYPE_TEXT => 'Plain Text',
        self::TYPE_TEXTAREA => 'Text area',
        self::TYPE_HTML => 'HTML',
        self::TYPE_DATE => 'Date',
        self::TYPE_YES_NO => 'Yes / No',
        self::TYPE_YES => 'Confirmation',
        self::TYPE_VARIATIONS => 'Variations',
        self::TYPE_SECTION => 'Section',
        self::TYPE_BMI => 'BMI logic',
        self::TYPE_IMAGE => 'Image',
        self::TYPE_NOTIFY_GP => 'Notify GP',
        self::TYPE_ALLERGIES => 'Health Profile - Allergies',
        self::TYPE_MEDICATIONS => 'Health Profile - Medications',
        self::TYPE_CONDITIONS => 'Health Profile - Conditions',
        self::TYPE_ALERT => 'Error Message',
        self::TYPE_INFORMATION => 'Warning Message',
        self::TYPE_INFORMATION_GREEN => 'Success Message',
        self::TYPE_NUMBER => 'Number',
        self::TYPE_EMAIL => 'Email',
        self::TYPE_WEIGHT => 'Weight',
        self::TYPE_BP_READINGS => 'Blood Pressure readings',
    ];

    public static $question_subtypes = [
        self::TYPE_IMAGE => [
            self::TYPE_IMAGE => 'Generic image',
            self::TYPE_BP_IMAGE => 'Blood Pressure Image',
            self::TYPE_ID_IMAGE => 'ID Image',
            self::TYPE_SELFIE_IMAGE => 'Selfie Image',
        ],
    ];



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

    /**
     * Define the relationship to Answers
     * @return hasMany
     */
    public function answers(): hasMany
    {
        return $this->hasMany(Answer::class, 'question_id');
    }

    /**
     * @param Builder $query Query builder object
     * @return Builder
     *
     */

    public function scopeActive(Builder $query): Builder
    {
        return $query->where('is_active', 1);
    }

    /**
     * Check if file is expected as an answer
     *
     * @return bool
     */
    public function expectsFile()
    {
        return in_array($this->question_type, Question::$file_question_types);
    }

    /**
     * Check if file mime type is valid
     *
     * @param UploadedFile $uploaded_file
     */
    public function isValidFileFormat($uploaded_file)
    {
        if (empty($uploaded_file)) {
            return $this->is_required;
        }
        return in_array($uploaded_file->getMimeType(), self::$file_type_allowed_mimes[$this->question_type]);
    }

    /**
     * Normalize the variations JSON into a consistent [{label, image}] shape.
     * Supports both the legacy format (array of strings) and the current format (array of objects).
     */
    public static function normalizeVariations($raw): array
    {
        $decoded = json_decode((string) $raw, true);
        if (!is_array($decoded)) {
            return [];
        }

        $result = [];
        foreach ($decoded as $entry) {
            if (is_string($entry)) {
                $result[] = ['label' => $entry, 'image' => null];
            } elseif (is_array($entry) && isset($entry['label'])) {
                $result[] = [
                    'label' => (string) $entry['label'],
                    'image' => $entry['image'] ?? null,
                ];
            }
        }
        return $result;
    }
}
