<?php

namespace App\Services\PurchaseOrders;

use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderItem;
use App\Models\Supply;
use App\Models\SupplyTransaction;
use Illuminate\Support\Facades\DB;
use RuntimeException;

class PurchaseOrderReceiveService
{
    public function receive(int $poId, array $received, string $issuedBy): array
    {
        $po = PurchaseOrder::query()->find($poId);
        if (!$po || in_array($po->status, [PurchaseOrder::STATUS_CANCELED, PurchaseOrder::STATUS_RECEIVED], true)) {
            throw new RuntimeException('PO not receivable.');
        }

        if (empty($received)) {
            throw new RuntimeException('No items to receive.');
        }

        return DB::transaction(function () use ($po, $received, $issuedBy) {
            $completed = true;

            foreach ($received as $item) {
                $itemId = (int) ($item['id'] ?? 0);
                $qty = (int) ($item['quantity'] ?? 0);
                if ($itemId <= 0 || $qty <= 0) {
                    continue;
                }

                $poItem = PurchaseOrderItem::query()
                    ->where('purchase_order_id', $po->id)
                    ->where('id', $itemId)
                    ->first();

                if (!$poItem) {
                    $completed = false;
                    continue;
                }

                $remaining = (int) $poItem->quantity - (int) $poItem->received_qty;
                $toReceive = min($remaining, $qty);
                if ($toReceive <= 0) {
                    continue;
                }

                $poItem->received_qty = (int) $poItem->received_qty + $toReceive;
                $poItem->save();

                $supply = Supply::query()->find($poItem->supply_id);
                if (!$supply) {
                    $completed = false;
                    continue;
                }

                $supply->qty_on_hand = (int) $supply->qty_on_hand + $toReceive;
                $supply->save();

                SupplyTransaction::query()->create([
                    'supply_id' => $supply->id,
                    'type' => 'in',
                    'quantity' => $toReceive,
                    'ref' => 'PO ' . ($po->po_number ?? $po->id),
                    'issued_to' => 'Inventory',
                    'issued_by' => $issuedBy,
                    'notes' => 'Received against PO',
                ]);

                if ($poItem->received_qty < $poItem->quantity) {
                    $completed = false;
                }
            }

            $po->status = $completed ? PurchaseOrder::STATUS_RECEIVED : PurchaseOrder::STATUS_ORDERED;
            $po->save();

            return [
                'status' => $po->status,
                'completed' => $completed,
            ];
        });
    }
}
