<?php

namespace App\Services\AutoCount\Concerns;

use Throwable;

/**
 * Shared Dataverse-lookup + payload helpers for the AutoCount write-payload
 * builders (AutoCountWritePayloadBuilder, CashPaymentParamsBuilder).
 *
 * The using class must expose a DataverseService as `$this->dv`.
 */
trait ResolvesAutoCountLookups
{
    /**
     * Line amount: prefer the stored sub-amount, else compute qty*price - discount.
     */
    protected function amount(array $item): float
    {
        $total = $item['cr6f2_subamount'] ?? null;
        if ($total !== null && $total !== '') {
            return (float) $total;
        }
        $up   = (float) ($item['cr6f2_unitprice'] ?? 0);
        $qty  = (float) ($item['cr6f2_qty'] ?? 0);
        $disc = (float) ($item['cr6f2_discount'] ?? 0);
        return $up * $qty - $disc;
    }

    /** ISO date → YYYY-MM-DD (the write API accepts this). Empty → ''. */
    protected function fmtDate(?string $value): string
    {
        if (!$value) return '';
        return substr($value, 0, 10);
    }

    /** Distinct non-empty lookup GUIDs for a column across rows. */
    protected function ids(array $rows, string $column): array
    {
        return array_values(array_unique(array_filter(array_column($rows, $column))));
    }

    /** Fetch one lookup record (keyed by its primary id) or [] if missing. */
    protected function lookupOne(string $entitySet, string $pk, ?string $id, array $select): array
    {
        if (!$id) return [];
        $map = $this->batchMap($entitySet, $pk, [$id], $select);
        return $map[$id] ?? [];
    }

    /**
     * Batch-fetch records by id (id eq A or id eq B …), keyed by primary id.
     * Non-fatal on failure — returns whatever resolved.
     *
     * @return array<string, array>
     */
    protected function batchMap(string $entitySet, string $pk, array $ids, array $select): array
    {
        if (empty($ids)) return [];
        try {
            $filter = implode(' or ', array_map(fn($id) => "{$pk} eq {$id}", $ids));
            $result = $this->dv->get($entitySet, [
                'select' => array_merge([$pk], $select),
                'filter' => $filter,
                'top'    => count($ids),
            ]);
        } catch (Throwable) {
            return [];
        }
        $map = [];
        foreach ($result['value'] ?? [] as $row) {
            if (!empty($row[$pk])) {
                $map[$row[$pk]] = $row;
            }
        }
        return $map;
    }

    /**
     * Drop keys whose value is null or '' so we don't send noise to AutoCount.
     * $keep forces specific keys through even when their value is 0/empty
     * (e.g. Amount/DR/CR which are meaningful at 0).
     */
    protected function omitEmpty(array $arr, array $keep = []): array
    {
        $out = [];
        foreach ($arr as $k => $v) {
            if (in_array($k, $keep, true)) {
                $out[$k] = $v;
                continue;
            }
            if ($v === null || $v === '') continue;
            $out[$k] = $v;
        }
        return $out;
    }
}
