<?php

namespace App\Modules\Procurement\Services;

use App\Models\User;
use App\Modules\Procurement\Exceptions\ReceivingOperationalException;
use App\Modules\Procurement\Models\GoodsReceipt;
use App\Support\Bulk\BulkOperationResult;
use Illuminate\Support\Facades\Gate;

final class GoodsReceiptBulkValidateService
{
    public function __construct(
        private readonly GoodsReceiptLifecycleService $receiptLifecycle,
    ) {}

    /**
     * @param  list<int|string>  $ids
     */
    public function run(User $user, int $tenantId, array $ids): BulkOperationResult
    {
        $ids = $this->normalizeIds($ids);
        $succeeded = [];
        $failures = [];

        foreach ($ids as $id) {
            $gr = GoodsReceipt::query()->where('tenant_id', $tenantId)->whereKey($id)->first();
            if ($gr === null) {
                $failures[] = ['id' => $id, 'message' => __('procurement.bulk.receipt_not_found')];

                continue;
            }
            if (! Gate::forUser($user)->allows('transition', $gr)) {
                $failures[] = ['id' => $id, 'message' => __('procurement.bulk.forbidden')];

                continue;
            }
            try {
                $this->receiptLifecycle->markValidated($tenantId, (int) $gr->id);
                $succeeded[] = (int) $gr->id;
            } catch (ReceivingOperationalException $e) {
                $failures[] = ['id' => $id, 'message' => $e->getMessage()];
            }
        }

        return new BulkOperationResult($succeeded, $failures, __('procurement.bulk.label_validate_receipts'));
    }

    /**
     * @param  list<int|string>  $ids
     * @return list<int>
     */
    private function normalizeIds(array $ids): array
    {
        $out = [];
        foreach ($ids as $id) {
            $out[] = (int) $id;
        }
        $out = array_values(array_unique(array_filter($out, static fn (int $v) => $v > 0)));

        return array_slice($out, 0, 50);
    }
}
