<?php

namespace Modules\Transport\Services\Ai;

use App\Models\TransportContractSiteModel;

/**
 * Resolves which contracts to include in one AI plan run (region + batch cap).
 */
class AiPlanScopeService
{
    public const DEFAULT_BATCH_LIMIT = 40;

    protected TransportContractSiteModel $sites;

    public function __construct()
    {
        $this->sites = new TransportContractSiteModel();
    }

    public function normalizeBatchLimit(mixed $value): int
    {
        $limit = (int) $value;

        return in_array($limit, TransportContractSiteModel::BATCH_LIMITS, true)
            ? $limit
            : self::DEFAULT_BATCH_LIMIT;
    }

    public function normalizeRegion(mixed $value): ?string
    {
        $region = trim((string) ($value ?? ''));

        return $region !== '' ? $region : null;
    }

    /**
     * @param list<int|string>|null $postedContractIds
     *
     * @return array{
     *   contract_ids: list<int>,
     *   region: ?string,
     *   batch_limit: int,
     *   region_total: int,
     *   capped: bool,
     *   error: ?string
     * }
     */
    public function resolve(?array $postedContractIds, ?string $region, int $batchLimit): array
    {
        $region      = $this->normalizeRegion($region);
        $batchLimit  = $this->normalizeBatchLimit($batchLimit);
        $regionTotal = $region !== null
            ? $this->sites->countActivePlannable($region)
            : $this->sites->countActivePlannable();

        $ids = [];
        if (is_array($postedContractIds) && $postedContractIds !== []) {
            $ids = array_values(array_unique(array_filter(array_map('intval', $postedContractIds))));
            $ids = array_slice($ids, 0, $batchLimit);
        } elseif ($region !== null) {
            $ids = $this->sites->getActivePlannableContractIds($region, $batchLimit);
        } elseif ($regionTotal <= $batchLimit) {
            $ids = $this->sites->getActivePlannableContractIds(null, $batchLimit);
        }

        if ($ids === []) {
            $message = $regionTotal > $batchLimit
                ? sprintf(
                    'There are %d plannable contract sites. Choose a region (e.g. Budaiya) or select up to %d contracts for this run.',
                    $regionTotal,
                    $batchLimit
                )
                : 'No plannable contract sites were found for the selected scope.';

            return [
                'contract_ids' => [],
                'region'       => $region,
                'batch_limit'  => $batchLimit,
                'region_total' => $regionTotal,
                'capped'       => false,
                'error'        => $message,
            ];
        }

        $sourceTotal = $region !== null
            ? $regionTotal
            : ($postedContractIds !== null && $postedContractIds !== []
                ? count($postedContractIds)
                : $regionTotal);

        return [
            'contract_ids' => $ids,
            'region'       => $region,
            'batch_limit'  => $batchLimit,
            'region_total' => $region !== null ? $regionTotal : $this->sites->countActivePlannable(),
            'capped'       => $sourceTotal > count($ids),
            'error'        => null,
        ];
    }

    /**
     * Default selected contract ids for the generate form (first N in region).
     *
     * @return list<int>
     */
    public function defaultSelection(?string $region, int $batchLimit, array $sites): array
    {
        if ($region === null) {
            return [];
        }

        $ids = array_map(static fn (array $site): int => (int) $site['contract_id'], $sites);

        return array_slice($ids, 0, $this->normalizeBatchLimit($batchLimit));
    }
}
