<?php

declare(strict_types=1);

namespace App\Services\External;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;

/**
 * Баланс профиля DaData (резолв региона/ИНН лида). API: GET profile/balance
 * с заголовком Authorization: Token <api_key>.
 */
class DadataBalanceProvider implements BalanceProvider
{
    public function serviceKey(): string
    {
        return 'dadata';
    }

    public function fetch(): BalanceReading
    {
        try {
            $key = (string) config('services.dadata.api_key');
            if ($key === '') {
                return BalanceReading::fail('dadata', 'DaData api_key не задан');
            }
            // Эндпоинт profile/balance требует ОБА ключа: Authorization: Token <api_key>
            // И X-Secret: <secret> (иначе HTTP 401). secret — тот же, что для cleaner API.
            $headers = ['Authorization' => 'Token '.$key, 'Accept' => 'application/json'];
            $secret = (string) config('services.dadata.secret');
            if ($secret !== '') {
                $headers['X-Secret'] = $secret;
            }
            $resp = Http::timeout(10)
                ->withHeaders($headers)
                ->get((string) config('services.dadata.balance_url'));
            if (! $resp->ok()) {
                return BalanceReading::fail('dadata', 'HTTP '.$resp->status());
            }
            $balance = (float) ($resp->json('balance') ?? 0);

            return BalanceReading::ok('dadata', $balance, 'RUB', $this->dailySpend());
        } catch (\Throwable $e) {
            return BalanceReading::fail('dadata', $e->getMessage());
        }
    }

    /**
     * Оценка расхода/день: вызовы резолва за 7д × стоимость вызова.
     * Best-effort — любая ошибка подсчёта НЕ должна ронять чтение баланса.
     */
    private function dailySpend(): ?float
    {
        try {
            $costRub = ((int) config('services.dadata.call_cost_kopecks', 60)) / 100;
            $calls7d = DB::table('supplier_leads')
                ->where('region_source', 'dadata')
                ->where('received_at', '>=', now()->subDays(7))
                ->count();
            if ($calls7d === 0) {
                return null;
            }

            return round(($calls7d / 7) * $costRub, 2);
        } catch (\Throwable) {
            return null;
        }
    }
}
