<?php

namespace PortalPeople\virtualstock\models;

use PortalPeople\virtualstock\constants\OrderStatus;

/**
 * Represents a VirtualStock order as returned by the REST API.
 * This is a plain value object — not an ActiveRecord or DynamicModel.
 */
class Order
{
    public string $id = '';
    public string $orderReference = '';
    public string $status = '';
    public string $subStatus = '';
    public ?string $supplierId = null;
    public ?string $retailerId = null;
    public ?string $supplierDispatchDate = null;
    public ?string $supplierDeliveryDate = null;
    public ?string $createdAt = null;
    public ?string $updatedAt = null;

    /** @var OrderItem[] */
    public array $items = [];

    public ?ShippingAddress $shippingAddress = null;

    /** Raw API payload for any fields not explicitly mapped */
    public array $raw = [];

    public static function fromArray(array $data): self
    {
        $order = new self();
        $order->id              = (string) ($data['id'] ?? $data['order_id'] ?? '');
        $order->orderReference  = (string) ($data['order_reference'] ?? $data['orderReference'] ?? '');
        $order->status          = (string) ($data['status'] ?? '');
        $order->subStatus       = (string) ($data['sub_status'] ?? $data['subStatus'] ?? '');
        $order->supplierId      = isset($data['supplier_id']) ? (string) $data['supplier_id'] : null;
        $order->retailerId      = isset($data['retailer_id']) ? (string) $data['retailer_id'] : null;
        $order->supplierDispatchDate  = $data['supplier_dispatch_date'] ?? $data['supplierDispatchDate'] ?? null;
        $order->supplierDeliveryDate  = $data['supplier_delivery_date'] ?? $data['supplierDeliveryDate'] ?? null;
        $order->createdAt       = $data['created_at'] ?? $data['createdAt'] ?? null;
        $order->updatedAt       = $data['updated_at'] ?? $data['updatedAt'] ?? null;
        $order->raw             = $data;

        if (!empty($data['items']) && is_array($data['items'])) {
            foreach ($data['items'] as $item) {
                $order->items[] = OrderItem::fromArray($item);
            }
        }

        if (!empty($data['shipping_address']) && is_array($data['shipping_address'])) {
            $order->shippingAddress = ShippingAddress::fromArray($data['shipping_address']);
        } elseif (!empty($data['shippingAddress']) && is_array($data['shippingAddress'])) {
            $order->shippingAddress = ShippingAddress::fromArray($data['shippingAddress']);
        }

        return $order;
    }

    public function toArray(): array
    {
        return [
            'id'                    => $this->id,
            'order_reference'       => $this->orderReference,
            'status'                => $this->status,
            'sub_status'            => $this->subStatus,
            'supplier_id'           => $this->supplierId,
            'retailer_id'           => $this->retailerId,
            'supplier_dispatch_date' => $this->supplierDispatchDate,
            'supplier_delivery_date' => $this->supplierDeliveryDate,
            'created_at'            => $this->createdAt,
            'updated_at'            => $this->updatedAt,
            'items'                 => array_map(fn(OrderItem $i) => $i->toArray(), $this->items),
            'shipping_address'      => $this->shippingAddress?->toArray(),
        ];
    }

    public function getStatusLabel(): string
    {
        return OrderStatus::label($this->status);
    }

    public function canTransitionTo(string $status): bool
    {
        return OrderStatus::canTransitionTo($this->status, $status);
    }

    public function isDispatched(): bool
    {
        return $this->status === OrderStatus::DISPATCH;
    }

    public function isCancelled(): bool
    {
        return in_array($this->status, [OrderStatus::CANCEL, OrderStatus::CANCEL_ACK], true);
    }
}
