<?php

namespace App\Services\AgentSettlement;

use Illuminate\Support\Facades\DB;

/**
 * 账期汇总尾差归平台（§21.8）。
 */
final class PlatformRoundingAdjuster
{
    /**
     * @param  array{players: array<int, array<string, mixed>>, agent_edges: array<string, int>, agent_subtrees: array<int, array<string, mixed>>}  $aggregate
     */
    public function apply(int $periodId, array $aggregate): int
    {
        $playerNet = 0;
        foreach ($aggregate['players'] as $row) {
            $playerNet += (int) $row['net_amount'];
        }

        $shareProfitTotal = 0;
        foreach ($aggregate['agent_subtrees'] as $subtree) {
            $shareProfitTotal += (int) ($subtree['share_profit'] ?? 0);
        }
        $shareProfitTotal += (int) ($aggregate['platform_share_profit'] ?? 0);

        $diff = $playerNet - $shareProfitTotal;
        if ($diff === 0) {
            return 0;
        }

        $platformBill = DB::table('settlement_bills')
            ->where('settlement_period_id', $periodId)
            ->where('bill_type', 'agent')
            ->where('counterparty_type', 'platform')
            ->orderBy('id')
            ->first();

        if ($platformBill === null) {
            return 0;
        }

        $net = (int) $platformBill->net_amount + $diff;
        DB::table('settlement_bills')->where('id', (int) $platformBill->id)->update([
            'platform_rounding_adjustment' => $diff,
            'net_amount' => $net,
            'unpaid_amount' => abs($net),
            'meta_json' => json_encode(array_merge(
                $this->decodeMeta($platformBill->meta_json),
                ['platform_rounding_adjustment' => $diff],
            )),
            'updated_at' => now(),
        ]);

        return $diff;
    }

    /**
     * @return array<string, mixed>
     */
    private function decodeMeta(mixed $raw): array
    {
        if ($raw === null || $raw === '') {
            return [];
        }

        $decoded = is_string($raw) ? json_decode($raw, true) : $raw;

        return is_array($decoded) ? $decoded : [];
    }
}
