<?php

declare(strict_types=1);

namespace App\Support;

use App\Models\DberpCustomer;
use App\Models\DberpSettlementWriteOff;
use App\Models\DberpSupplier;
use Illuminate\Support\Collection;

/**
 * 核销列表 counterparty 名称批量解析，避免逐行 value() 查询。
 */
final class DberpSettlementWriteOffCounterpartyNames
{
    /**
     * @var array<int, string>
     */
    private array $customers = [];

    /**
     * @var array<int, string>
     */
    private array $suppliers = [];

    /**
     * @param  iterable<int, DberpSettlementWriteOff>|Collection<int, DberpSettlementWriteOff>  $records
     */
    public function preload(iterable $records): void
    {
        $this->customers = [];
        $this->suppliers = [];

        $collection = $records instanceof Collection ? $records : collect($records);

        if ($collection->isEmpty()) {
            return;
        }

        $customerIds = $collection
            ->where('counterparty_type', 'customer')
            ->pluck('counterparty_id')
            ->filter()
            ->unique()
            ->map(fn (mixed $id): int => (int) $id)
            ->all();

        $supplierIds = $collection
            ->where('counterparty_type', 'supplier')
            ->pluck('counterparty_id')
            ->filter()
            ->unique()
            ->map(fn (mixed $id): int => (int) $id)
            ->all();

        if ($customerIds !== []) {
            $this->customers = DberpCustomer::query()
                ->whereIn('id', $customerIds)
                ->pluck('name', 'id')
                ->all();
        }

        if ($supplierIds !== []) {
            $this->suppliers = DberpSupplier::query()
                ->whereIn('id', $supplierIds)
                ->pluck('name', 'id')
                ->all();
        }
    }

    public function name(DberpSettlementWriteOff $record): string
    {
        $counterpartyId = (int) $record->counterparty_id;

        if ($record->counterparty_type === 'supplier') {
            return $this->suppliers[$counterpartyId] ?? (string) $record->counterparty_id;
        }

        return $this->customers[$counterpartyId] ?? (string) $record->counterparty_id;
    }
}
