<?php

namespace App\Domains\Catalog\Models;

use App\Domains\Attachable\Models\Attachment;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;

#[Fillable([
    'catalog_item_id',
    'inventory_id',
    'minimum_use_date',
    'maximum_use_date',
])]
class Variant extends Model
{
    use HasFactory;

    public $timestamps = false;

    protected $table = 'variantes';

    protected function casts(): array
    {
        return [
            'catalog_item_id' => 'integer',
            'inventory_id' => 'integer',
            'minimum_use_date' => 'datetime',
            'maximum_use_date' => 'datetime',
        ];
    }

    /** @return BelongsTo<CatalogItem, $this> */
    public function catalogItem(): BelongsTo
    {
        return $this->belongsTo(CatalogItem::class);
    }

    /** @return BelongsTo<Inventory, $this> */
    public function inventory(): BelongsTo
    {
        return $this->belongsTo(Inventory::class);
    }

    /** @return HasMany<VariantDefinition, $this> */
    public function definitions(): HasMany
    {
        return $this->hasMany(VariantDefinition::class);
    }

    /** @return BelongsToMany<Attachment, $this> */
    public function attachments(): BelongsToMany
    {
        $relation = $this->belongsToMany(
            Attachment::class,
            'catalog_items_attachments',
            'variant_id',
            'attachment_id'
        )
            ->withPivot('orden')
            ->orderByPivot('orden');

        if ($this->catalog_item_id !== null) {
            $relation->withPivotValue('catalog_item_id', $this->catalog_item_id);
        }

        return $relation;
    }

    public function getPrice(): float
    {
        return $this->catalogItem->getPrice();
    }

    public function getName(): string
    {
        $name = $this->catalogItem->nombre;
        $this->loadMissing('definitions.itemAttribute.attribute');
        $definitions = $this->definitions
            ->map(function (VariantDefinition $definition): ?string {
                $attributeName = $definition->itemAttribute?->attribute?->nombre;

                return $attributeName
                    ? "{$attributeName}: {$definition->value}"
                    : $definition->value;
            })
            ->filter()
            ->implode(', ');

        return $definitions === '' ? $name : "{$name} ({$definitions})";
    }

    public function getMinimumUseDate(): ?CarbonInterface
    {
        return $this->minimum_use_date
            ?? $this->catalogItem->getMinimumUseDate();
    }

    public function getMaximumUseDate(): ?CarbonInterface
    {
        return $this->maximum_use_date
            ?? $this->catalogItem->getMaximumUseDate();
    }
}
