<?php

namespace App\Enums\Invoicing;

use App\Models\Hotel\Reservation;
use App\Models\Modules\OtaConnections\ExternalReservation;
use App\Models\Restaurant\Order;

enum BillableService: string
{
    case Reservation         = 'reservation';
    case ExternalReservation = 'external-reservation';
    case Order               = 'order';

    /**
     * Obtiene la clase de modelo Eloquent asociada al tipo de servicio facturable.
     *
     * @return class-string Eloquent model class asociada al valor del enum.
     */
    public function modelClass(): string
    {
        return match ($this) {
            self::Reservation         => Reservation::class,
            self::ExternalReservation => ExternalReservation::class,
            self::Order               => Order::class,
        };
    }

    /**
     * Resuelve el valor del enum a partir de la clase de modelo Eloquent proporcionada.
     *
     * @param class-string $class Clase de modelo Eloquent (FQCN) para la que se desea el enum.
     * @return self|null  Instancia de BillableService correspondiente, o null si no hay coincidencia.
     */
    public static function fromModelClass(string $class): ?self
    {
        foreach (self::cases() as $case) {
            if ($case->modelClass() === $class) {
                return $case;
            }
        }

        return null;
    }

    /**
     * Obtiene la etiqueta traducida correspondiente al tipo de servicio facturable.
     *
     * @return string Etiqueta traducida del valor del enum.
     */
    public function label(): string
    {
        return match ($this) {
            self::Reservation         => __('entities')['hotel']['reservation'],
            self::ExternalReservation => __('entities')['hotel']['reservation'],
            self::Order               => __('entities')['restaurant']['order'],
        };
    }

    /**
     * Obtiene la etiqueta traducida desde diversos tipos de valores:
     *
     * - Un valor del enum (BillableService)
     * - Un string con el valor del enum ('reservation', 'order', etc.)
     * - Un FQCN de modelo Eloquent (por ejemplo Reservation::class)
     *
     *
     * @param mixed $value Instancia del enum, string o clase de modelo.
     *
     * @return string|null Etiqueta traducida, o null si no se puede determinar.
     */
    public static function labelFrom(mixed $value): ?string
    {
        // Enum value provided
        if ($value instanceof self)
            return $value->label();

        // String Enum value provided
        if (is_string($value)) {
            foreach (self::cases() as $case) {
                if ($case->value === $value) {
                    return $case->label();
                }
            }
        }

        // String-Class provided
        foreach (self::cases() as $case) {
            if ($case->modelClass() === $value) {
                return $case->label();
            }
        }

        // Not recognized value
        return null;
    }
}
