<?php

namespace App\Modules\Procurement\Services;

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

final class PurchaseOrderBulkApproveService
{
    public function __construct(
        private readonly PurchaseOrderLifecycleService $lifecycle,
    ) {}

    /**
     * @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) {
            $po = PurchaseOrder::query()->where('tenant_id', $tenantId)->whereKey($id)->first();
            if ($po === null) {
                $failures[] = ['id' => $id, 'message' => __('procurement.bulk.not_found')];

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

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

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

    /**
     * @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);
    }
}
