<?php

namespace Modules\Inventory\Services;

use Illuminate\Support\Facades\DB;
use Modules\Core\Exceptions\BusinessException;
use Modules\Core\Traits\HasActionContext;
use Modules\Inventory\Enums\PurchaseRequisitionStatusEnum;
use Modules\Inventory\Enums\PurchaseStatusEnum;
use Modules\Inventory\Models\PurchaseInvoice;
use Modules\Inventory\Repositories\PurchaseRepository;
use Modules\Inventory\Repositories\PurchaseRequisitionRepository;

class PurchasePostingService
{
    use HasActionContext;

    public function __construct(
        protected PurchaseRepository $purchaseRepo,
        protected PurchaseRequisitionRepository $purchaseReqRepo,
        private PurchaseVoucherService $purchaseVoucherService,
        private PurchaseInventoryService $purchaseInvService,
        private PurchaseAssetService $purchaseAstService,
    ) { }

    public function posting(PurchaseInvoice $invoice): PurchaseInvoice {
        return DB::transaction(function () use ($invoice) {
            $this->validateApproval($invoice);
            
            $voucher = $this->purchaseVoucherService->create($invoice);

            $this->purchaseInvService->receivePurchase($invoice);

            //$this->purchaseAstService->createFromPurchase($invoice);

            $invoicePayload = [
                'voucher_id' => $voucher?->id,
                'status'     => PurchaseStatusEnum::POSTED->value,
                'is_posted' => true,
                ...$this->attach('posted_by', 'posted_at'),
            ];

            $this->purchaseRepo->updateInvoice(
                $invoice,
                $invoicePayload
            );

            if($invoice->purchaseRequisition){
                $this->purchaseReqRepo->update(
                    requisition: $invoice->purchaseRequisition,
                    data: [
                        'status' => PurchaseRequisitionStatusEnum::CLOSED->value,
                        'closed_at' => now(),
                    ]
                );
            }

            return $invoice->fresh();
        });
    }

    private function validateApproval(PurchaseInvoice $invoice): void
    {
        if (!$invoice->isEligibleForPosting()) {
            BusinessException::message('Purchase invoice cannot be posted.');
        }

        if ($invoice->items->isEmpty()) {
            BusinessException::message('Purchase invoice contains no items.');
        }

        if ($invoice->grand_total <= 0) {
            BusinessException::message('Grand total must be greater than zero.');
        }

        if ($invoice->purchaseRequisition === null) {
            BusinessException::message(
                'Purchase requisition not found.'
            );
        }
    }
}
