<?php

namespace App\Services\Billing;

use Illuminate\Support\Facades\Http;

/**
 * Client for the platform Billing HTTP API — the one UserWallet lives on the
 * platform; CRM only consumes it. Amounts are integer minor units; the user is
 * identified by public_id. Authenticates with the per-consumer config('billing.api_key').
 */
class BillingClient
{
    private function base(): string
    {
        return rtrim((string) config('billing.api_url'), '/');
    }

    private function token(): string
    {
        return (string) (config('billing.api_key') ?? '');
    }

    public function balanceMinor(string $publicId): int
    {
        $res = Http::withToken($this->token())->acceptJson()->timeout(8)
            ->get($this->base().'/balance', ['user' => $publicId]);
        $res->throw();

        return (int) ($res->json('balance_minor') ?? 0);
    }

    public function canAfford(string $publicId, int $amountMinor): bool
    {
        $res = Http::withToken($this->token())->acceptJson()->timeout(8)
            ->get($this->base().'/can-afford', ['user' => $publicId, 'amount_minor' => $amountMinor]);
        $res->throw();

        return (bool) ($res->json('affordable') ?? false);
    }

    /**
     * Debit the wallet. Returns true on success, false on insufficient balance
     * (HTTP 402). Idempotent by $reference.
     */
    public function debit(string $publicId, int $amountMinor, string $source, string $reference, ?string $description = null): bool
    {
        $res = Http::withToken($this->token())->acceptJson()->timeout(10)->post($this->base().'/debit', array_filter([
            'user' => $publicId,
            'amount_minor' => $amountMinor,
            'service' => (string) config('billing.service', 'crm'),
            'source' => $source,
            'reference' => $reference,
            'description' => $description,
        ], static fn ($v) => $v !== null));

        if ($res->status() === 402) {
            return false;
        }
        $res->throw();

        return true;
    }
}
