<?php

namespace App\Services\Pagarme\Concerns;

use App\Data\Pagarme\PagarmeData;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Throwable;

trait SendsPagarmeRequests
{
    protected function pagarmeRequest(
        string $method,
        string $path,
        string $idempotencyKey,
        string $errorMessage, array|PagarmeData $payload,
    ): array {
        $payload  = $payload instanceof PagarmeData ? $payload->toArray() : $payload;
        $endpoint = $this->pagarmeUrl($path);

        try {
            $response = $this->pagarmeHttp($idempotencyKey)
                ->send($method, $endpoint, ['json' => $payload])
                ->throw();

            $result = $response->json() ?? [];

            if (app()->environment('local', 'development')) {
                Log::channel('pagarme')->info('Requisição ao Pagar.me concluída com sucesso', [
                    'method'    => strtoupper($method),
                    'endpoint'  => $endpoint,
                    'origin_ip' => $this->pagarmeOriginIp(),
                    'payload'   => $payload,
                    'result'    => $result,
                ]);
            }

            return $result;
        } catch (Throwable $e) {
            $responseBody = null;

            if (method_exists($e, 'getResponse')) {
                $responseBody = $e->getResponse()?->json();
            } elseif (isset($e->response)) {
                $responseBody = $e->response->json();
            }

            Log::channel('pagarme')->error('Falha na requisição ao Pagar.me', [
                'method'    => strtoupper($method),
                'endpoint'  => $endpoint,
                'origin_ip' => $this->pagarmeOriginIp(),
                'payload'   => $payload,
                'exception' => $e->getMessage(),
                'result'    => $responseBody,
            ]);

            $message = $errorMessage;
            $errors  = data_get($responseBody, 'errors', []);

            if ($errors) {
                $details = [];

                foreach ($errors as $field => $msgs) {
                    foreach ((array) $msgs as $msg) {
                        $details[] = $msg;
                    }
                }

                if ($details) {
                    $message .= ': '.implode(' ', $details);
                }
            }

            throw new \RuntimeException($message, previous: $e);
        }
    }

    //

    protected function pagarmeHttp(string $idempotencyKey)
    {
        $secretKey = config('services.pagarme.secret_key');

        if (empty($secretKey)) {
            Log::channel('pagarme')->error('Chave PAGARME_SECRET_KEY não está configurada.');

            throw new \RuntimeException('PAGARME_SECRET_KEY is not configured.');
        }

        return Http::withBasicAuth($secretKey, '')
            ->withHeaders([
                'Idempotency-Key' => $idempotencyKey,
                'Content-Type'    => 'application/json',
                'Accept'          => 'application/json',
            ]);
    }

    protected function pagarmeOriginIp(): ?string
    {
        try {
            return trim(Http::timeout(3)->get('https://api.ipify.org')->body()) ?: null;
        } catch (Throwable) {
            return null;
        }
    }

    //

    protected function pagarmeUrl(string $path): string
    {
        return rtrim(config('services.pagarme.base_url'), '/').'/'.ltrim($path, '/');
    }
}
