<?php

namespace Daylight\Core\Models;

use App\Models\User;
use Daylight\Core\Models\Enums\AddressType;
use Daylight\Core\Models\Enums\OrderStatus;
use Daylight\Core\Models\Enums\PaymentMethod;
use Daylight\Core\Models\Enums\ShippingMethod;
use Daylight\Core\Modules\Payment\Enums\PaymentStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class Order extends Model
{
    protected $guarded = [];

    protected $casts = [
        'tax_breakdown' => 'json',
        'status' => OrderStatus::class,
        'payment_gateway_status' => PaymentStatus::class,
        'payment_method' => PaymentMethod::class,
        'shipping_method' => ShippingMethod::class,
    ];

    protected static function boot(): void
    {
        parent::boot();

        static::creating(function (Order $order) {
            $order->uuid = (string) Str::uuid();

            if (is_null($order->number)) {
                $order->number = static::generateOrderNumber();
            }
        });
    }

    private static function generateOrderNumber(): int
    {
        return intval(10000000 + intval(self::count() + 1));
    }

    public function customer(): BelongsTo
    {
        return $this->belongsTo(daylightModel('customer'));
    }

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

    public function items(): HasMany
    {
        return $this->hasMany(daylightModel('order_item'));
    }

    public function addresses(): HasMany
    {
        return $this->hasMany(daylightModel('order_address'));
    }

    public function updates(): HasMany
    {
        return $this->hasMany(daylightModel('order_update'))->latest();
    }

    public function billingAddress(): HasOne
    {
        return $this->addresses()->one()->ofMany([
            'id' => 'max',
        ], function (Builder $builder) {
            $builder->whereType(AddressType::BILLING);
        });
    }

    public function shippingAddress(): HasOne
    {
        return $this->addresses()->one()->ofMany([
            'id' => 'max',
        ], function (Builder $builder) {
            $builder->whereType(AddressType::SHIPPING);
        });
    }

    public function orderNumber(): Attribute
    {
        return Attribute::make(
            get: function () {
                return $this->number;
            }
        );
    }

    public function getTemporaryId(): ?int
    {
        return $this->temporary_id;
    }

    public function getOrderNumber(): string
    {
        return $this->number;
    }

    public function getCustomerNumber(): int
    {
        return $this->customer->imdex_id;
    }

    public function getDeliveryAddressNumber(): int
    {
        return $this->items->first()->deliveryAddress->imdex_id;
    }

    public function getOrderLines(): Collection
    {
        return $this->items;
    }
}
