<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Str;

/**
 * Service Order Model
 *
 * @property string $id
 * @property string $user_id
 * @property string $vendor_service_id
 * @property string $order_number
 * @property array $items
 * @property float $total_amount
 * @property float $vendor_amount
 * @property float $platform_fee
 * @property string $currency
 * @property string $status
 * @property string|null $delivery_address
 * @property string|null $customer_notes
 * @property string|null $vendor_notes
 * @property \Illuminate\Support\Carbon|null $paid_at
 * @property \Illuminate\Support\Carbon|null $delivered_at
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property \Illuminate\Support\Carbon|null $deleted_at
 * @property-read \App\Models\User $customer
 * @property-read \App\Models\VendorService $service
 * @method static \Illuminate\Database\Eloquent\Builder<ServiceOrder>|ServiceOrder newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder<ServiceOrder>|ServiceOrder query()
 */
class ServiceOrder extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * Indicates if IDs are auto-incrementing.
     *
     * @var bool
     */
    public $incrementing = false;

    /**
     * The data type of auto-incrementing ID.
     *
     * @var string
     */
    protected $keyType = 'string';

    protected $fillable = [
        'user_id',
        'vendor_service_id',
        'order_number',
        'items',
        'total_amount',
        'vendor_amount',
        'platform_fee',
        'currency',
        'status',
        'delivery_address',
        'customer_notes',
        'vendor_notes',
        'delivery_date',
        'paid_at',
        'delivered_at',
    ];

    protected $casts = [
        'items' => 'array',
        'total_amount' => 'decimal:2',
        'vendor_amount' => 'decimal:2',
        'platform_fee' => 'decimal:2',
        'paid_at' => 'datetime',
        'delivered_at' => 'datetime',
        'delivery_date' => 'datetime',
    ];

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

        static::creating(function ($order) {
            if (empty($order->id)) {
                $order->id = (string) Str::uuid();
            }
            if (empty($order->order_number)) {
                $order->order_number = 'ORD-' . strtoupper(Str::random(8));
            }
        });
    }

    /**
     * Get the customer who placed the order.
     */
    public function customer(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * Get the service being ordered.
     */
    public function service(): BelongsTo
    {
        return $this->belongsTo(VendorService::class, 'vendor_service_id');
    }

    /**
     * Scope to get orders by customer.
     */
    public function scopeByCustomer($query, $customerId)
    {
        return $query->where('user_id', $customerId);
    }

    /**
     * Scope to get orders by vendor.
     */
    public function scopeByVendor($query, $vendorId)
    {
        return $query->whereHas('service', function ($serviceQuery) use ($vendorId) {
            return $serviceQuery->where('user_id', $vendorId);
        });
    }

    /**
     * Scope to get orders by status.
     */
    public function scopeByStatus($query, $status)
    {
        return $query->where('status', $status);
    }

    /**
     * Get the formatted total amount.
     */
    public function getFormattedTotalAttribute()
    {
        return $this->currency . ' ' . number_format($this->total_amount, 2);
    }

    /**
     * Get the formatted vendor amount.
     */
    public function getFormattedVendorAmountAttribute()
    {
        return $this->currency . ' ' . number_format($this->vendor_amount, 2);
    }

    /**
     * Check if order is paid.
     */
    public function isPaid(): bool
    {
        return !is_null($this->paid_at);
    }

    /**
     * Check if order is delivered.
     */
    public function isDelivered(): bool
    {
        return !is_null($this->delivered_at);
    }
}
