<?php

namespace App\Modules\Procurement\Services;

use App\Modules\Procurement\Models\GoodsReceipt;
use App\Modules\Procurement\Models\GoodsReceiptItem;
use App\Modules\Procurement\Models\PurchaseOrderItem;
use App\Modules\Procurement\Repositories\GoodsReceiptHydrationRepository;
use Illuminate\Database\Eloquent\Collection;

final class GoodsReceiptHydrationService
{
    public function __construct(
        private readonly GoodsReceiptHydrationRepository $repository,
    ) {}

    /**
     * @return Collection<int, GoodsReceiptItem>
     */
    public function hydrateForReceipt(int $tenantId, int $goodsReceiptId): Collection
    {
        $receipt = GoodsReceipt::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->whereKey($goodsReceiptId)
            ->firstOrFail();

        $rows = $this->repository->loadHydratableLines(
            $tenantId,
            $goodsReceiptId,
            (int) $receipt->purchase_order_id,
        );

        foreach ($rows as $line) {
            $this->assertInMemory($line, (int) $receipt->purchase_order_id, $tenantId);
        }

        return $rows;
    }

    private function assertInMemory(GoodsReceiptItem $line, int $expectedPurchaseOrderId, int $tenantId): void
    {
        $poi = PurchaseOrderItem::withoutGlobalScopes()->find((int) $line->purchase_order_item_id);
        if ($poi === null || $poi->trashed() || (int) $poi->purchase_order_id !== $expectedPurchaseOrderId) {
            throw new \RuntimeException('goods_receipt_hydration_invariant_failed');
        }
        if ((int) $poi->tenant_id !== $tenantId) {
            throw new \RuntimeException('goods_receipt_hydration_tenant_invariant_failed');
        }
    }
}
