<?php

namespace App\Domain\Inventory\Models;

use App\Domain\Inventory\Enums\ProductCustomizationType;
use App\Domain\Shared\Traits\BelongsToAcademy;
use App\Domain\Shared\Traits\HasUuid;
use App\Domain\Shared\Traits\ScopedThroughBranch;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class ProductCustomization extends Model
{
    use BelongsToAcademy, HasUuid, ScopedThroughBranch;

    /**
     * The parent whose branch this row inherits — a question about a product
     * belongs wherever the product belongs, and must not grow a branch of its
     * own to drift from it.
     */
    protected static string $branchScopeRelation = 'product';

    protected $fillable = [
        'academy_id',
        'product_id',
        'name_ar',
        'name',
        'type',
        'options',
        'is_required',
        'is_active',
        'sort_order',
    ];

    protected function casts(): array
    {
        return [
            'type' => ProductCustomizationType::class,
            'options' => 'array',
            'is_required' => 'boolean',
            'is_active' => 'boolean',
            'sort_order' => 'integer',
        ];
    }

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }

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

    public function isSelect(): bool
    {
        return $this->type === ProductCustomizationType::Select;
    }

    /**
     * The answers the desk is allowed to give — empty for a text field, which
     * accepts anything.
     *
     * @return array<int, string>
     */
    public function allowedValues(): array
    {
        if (!$this->isSelect()) {
            return [];
        }

        return array_values(array_filter(
            array_map(fn ($o) => is_string($o) ? trim($o) : '', $this->options ?? []),
            fn ($o) => $o !== ''
        ));
    }

    /**
     * Whether an answer the browser sent is one this question actually accepts.
     *
     * A select must match its own list exactly: the cart is a browser-settable
     * array, so "the dropdown only offered these" is not a check.
     */
    public function accepts(?string $value): bool
    {
        $value = trim((string) $value);

        if ($value === '') {
            return !$this->is_required;
        }

        if (!$this->isSelect()) {
            return mb_strlen($value) <= 255;
        }

        return in_array($value, $this->allowedValues(), true);
    }
}
