<?php

namespace App\Services\Wallet;

use App\Models\Player;
use App\Models\TransferOrder;
use Illuminate\Support\Collection;

/** 扫描结果追加主站幂等记录核对项。 */
final class WalletTransferMainSiteReconcileChecker
{
    public function __construct(
        private readonly HttpMainSiteWalletIdempotentProbeClient $probeClient,
    ) {}

    /**
     * @param  list<array{side_a_ref: string, side_b_ref: ?string, difference_amount: int, status: string}>  $items
     * @param  Collection<int, TransferOrder>  $orders
     * @return list<array{side_a_ref: string, side_b_ref: ?string, difference_amount: int, status: string}>
     */
    public function appendIssues(array $items, Collection $orders): array
    {
        $existingTransferNos = collect($items)
            ->map(fn (array $row): string => (string) ($row['side_a_ref'] ?? ''))
            ->filter()
            ->flip();

        $players = Player::query()
            ->whereIn('id', $orders->pluck('player_id')->unique()->all())
            ->get()
            ->keyBy('id');

        foreach ($orders as $order) {
            if (! $this->shouldProbeMainSite($order)) {
                continue;
            }

            $transferNo = (string) $order->transfer_no;
            if ($existingTransferNos->has($transferNo)) {
                continue;
            }

            $player = $players->get((int) $order->player_id);
            if (! $player instanceof Player) {
                continue;
            }

            $probe = $this->probeClient->probe($player, (string) $order->idempotent_key);
            if ($probe->status === MainSiteWalletIdempotentProbeResult::STATUS_SKIPPED) {
                continue;
            }

            if ($probe->status === MainSiteWalletIdempotentProbeResult::STATUS_NOT_FOUND) {
                $items[] = [
                    'side_a_ref' => $transferNo,
                    'side_b_ref' => null,
                    'difference_amount' => (int) $order->amount,
                    'status' => 'main_site_record_missing',
                ];
                continue;
            }

            if ($probe->status === MainSiteWalletIdempotentProbeResult::STATUS_FAILED) {
                $items[] = [
                    'side_a_ref' => $transferNo,
                    'side_b_ref' => $probe->externalRefNo,
                    'difference_amount' => (int) $order->amount,
                    'status' => 'main_site_failed',
                ];
            }
        }

        return $items;
    }

    private function shouldProbeMainSite(TransferOrder $order): bool
    {
        if (trim((string) $order->external_ref_no) !== '') {
            return true;
        }

        if ($order->status === 'success') {
            return true;
        }

        return $order->direction === 'in'
            && $order->status === 'pending_reconcile'
            && $order->fail_reason === 'lottery_credit_failed';
    }
}
