<?php

namespace App\Services\Payments;

use App\Exceptions\Payments\PaystackException;
use App\Services\SystemSettingService;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http;

class PaystackService
{
    public function __construct(
        protected SystemSettingService $systemSettingService
    ) {
    }

    public function isConfigured(): bool
    {
        return filled($this->setting('secret_key'));
    }

    public function initializeTransaction(array $payload): array
    {
        $this->assertConfigured();

        $email = (string) ($payload['email'] ?? '');
        $reference = (string) ($payload['reference'] ?? '');
        $amount = (float) ($payload['amount'] ?? 0);

        if ($email === '' || $reference === '' || $amount <= 0) {
            throw new PaystackException('Invalid Paystack funding payload.');
        }

        $body = [
            'email' => $email,
            'amount' => (int) round($amount * 100),
            'reference' => $reference,
            'callback_url' => (string) ($payload['callback_url'] ?? ''),
            'metadata' => $payload['metadata'] ?? [],
            'channels' => array_values(array_filter((array) ($payload['channels'] ?? []))),
        ];

        if ($body['callback_url'] === '') {
            unset($body['callback_url']);
        }
        if (empty($body['channels'])) {
            unset($body['channels']);
        }

        $response = $this->client()
            ->withToken((string) $this->setting('secret_key'))
            ->post('/transaction/initialize', $body);

        $json = $response->json() ?? [];
        $ok = (bool) data_get($json, 'status', false);

        if (! $response->successful() || ! $ok) {
            throw new PaystackException(
                (string) (data_get($json, 'message') ?? 'Unable to initialize Paystack transaction.')
            );
        }

        $authorizationUrl = (string) (data_get($json, 'data.authorization_url') ?? '');
        if ($authorizationUrl === '') {
            throw new PaystackException('Paystack authorization URL is missing.');
        }

        return [
            'authorization_url' => $authorizationUrl,
            'access_code' => (string) (data_get($json, 'data.access_code') ?? ''),
            'reference' => (string) (data_get($json, 'data.reference') ?? $reference),
            'raw' => $json,
        ];
    }

    protected function client(): PendingRequest
    {
        return Http::acceptJson()
            ->contentType('application/json')
            ->timeout((int) $this->setting('timeout', 30))
            ->baseUrl(rtrim((string) $this->setting('base_url'), '/'));
    }

    protected function assertConfigured(): void
    {
        if (! $this->isConfigured()) {
            throw new PaystackException('Paystack is not configured. Set Paystack credentials in Admin Integration Settings.');
        }
    }

    protected function setting(string $key, mixed $default = null): mixed
    {
        $fallback = match ($key) {
            'base_url' => config('services.paystack.base_url', 'https://api.paystack.co'),
            'public_key' => config('services.paystack.public_key'),
            'secret_key' => config('services.paystack.secret_key'),
            'timeout' => config('services.paystack.timeout', 30),
            default => $default,
        };

        $value = $this->systemSettingService->get('payments.paystack', $key, $fallback);

        if (is_string($value) && trim($value) === '') {
            return $fallback ?? $default;
        }

        return $value ?? $default ?? $fallback;
    }
}

