<?php

namespace App\Service\ThirdParty;

use App\Service\ThirdParty\Interfaces\PaymentGatewayInterface;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

class BaniService implements PaymentGatewayInterface
{

    protected $client;
    protected string $baseUrl;
    protected string $accessToken;
    protected string $publicKey;
    protected string $privateKey;
    protected string $tribeAccountRef;

    public function __construct()
    {
        $this->client = new Client();
        $this->baseUrl = config('thirdparty.bani.base_url');
        $this->accessToken = config('thirdparty.bani.access_token');
        $this->publicKey = config('thirdparty.bani.public_key');
        $this->privateKey = config('thirdparty.bani.private_key');
        $this->tribeAccountRef = config('thirdparty.bani.tribe_account_ref');
    }

    protected function generateMoniSignature(): string
    {
        $diget = "{$this->tribeAccountRef}.{$this->publicKey}";
        return hash_hmac('sha256', $diget, $this->privateKey);
    }

    protected function getHeaders(): array
    {
        return [
            'Authorization' => 'Bearer ' . $this->accessToken,
            'MONI-SIGNATURE' => $this->generateMoniSignature(),
            'Content-Type' => 'application/json',
        ];
    }

    /**
     * Generate a virtual account.
     *
     * @param array $customerDetails
     * @return array
     * @throws GuzzleException
     */
    public function generateVirtualAccount(array $customerDetails)
    {
        $url = $this->baseUrl . '/api/v1/virtual-accounts';
        // Extract required fields from $customerDetails
        $accountName = $customerDetails['account_name'];
        $customerBvn = $customerDetails['bvn'];
        $customerId = $customerDetails['user_id'];
        $refCode = $customerDetails['reference_code'];

        // Transform the request payload
        $payload = [
            'pay_va_step' => 'direct',
            'country_code' => 'NG',
            'pay_currency' => 'NGN',
            'holder_account_type' => 'permanent',
            'alternate_name' => $accountName,
            'holder_legal_number' => $customerBvn,
            'customer_ref' => $customerId,
            'pay_ext_ref' => $refCode,
            'bank_name' => '9 payment service bank',
        ];

        $response = $this->client->post($url, [
            'headers' => $this->getHeaders(),
            'json' => $payload,
        ]);

        $responseData = json_decode($response->getBody(), true);

        // Normalize the response
        return $this->normalizeResponse($responseData, 'virtual_account');
    }

    /**
     * Check the status of a transaction.
     *
     * @param string $transactionReference
     * @return array
     * @throws GuzzleException
     */
    public function checkTransactionStatus(string $transactionReference): array
    {
        $url = $this->baseUrl . '/api/v1/transactions/' . $transactionReference;

        $response = $this->client->get($url, [
            'headers' => $this->getHeaders(),
        ]);

        $responseData = json_decode($response->getBody(), true);

        return $this->normalizeResponse($responseData, 'check_transaction_status');
    }

    /**
     * Verify a bank account.
     *
     * @param string $accountNumber
     * @param string $bankCode
     * @return array
     * @throws GuzzleException
     */
    public function verifyBankAccount(array $accountDetails): array
    {
        $url = $this->baseUrl . '/api/v1/accounts/verify';

        $response = $this->client->post($url, [
            'headers' => $this->getHeaders(),
            'json' => [
                'account_number' => $accountDetails['accountNumber'],
                'bank_code' => $accountDetails['bankCode'],
            ],
        ]);

        $responseData = json_decode($response->getBody(), true);

        return $this->normalizeResponse($responseData, 'verify_bank_account');
    }

    /**
     * Transfer funds to a recipient.
     *
     * @param array $transferDetails
     * @return array
     * @throws GuzzleException
     */
    public function transferFunds(array $transferDetails): array
    {
        $url = $this->baseUrl . '/api/v1/transfers';

        $response = $this->client->post($url, [
            'headers' => $this->getHeaders(),
            'json' => $transferDetails,
        ]);

        $responseData = json_decode($response->getBody(), true);

        return $this->normalizeResponse($responseData, 'transfer_funds');
    }

    /**
     * Initiate a payment.
     *
     * @param array $paymentDetails
     * @return array
     * @throws GuzzleException
     */
    public function initiatePayment(array $paymentDetails): array
    {
        $url = $this->baseUrl . '/api/v1/payments';

        $response = $this->client->post($url, [
            'headers' => $this->getHeaders(),
            'json' => $paymentDetails,
        ]);

        $responseData = json_decode($response->getBody(), true);

        return $this->normalizeResponse($responseData, 'initiate_payment');
    }

    /**
     * Normalize the response from Bani.
     *
     * @param array $responseData
     * @param string $action
     * @return array
     */
    protected function normalizeResponse(array $responseData, string $action): array
    {
        switch ($action) {
            case 'virtual_account':
                return [
                    'status' => $responseData['status'] === 'success' ? 'success' : 'failed',
                    'message' => $responseData['message'] ?? 'Virtual account created successfully',
                    'data' => [
                        'account_number' => $responseData['data']['virtual_account_number'],
                        'bank_name' => $responseData['data']['bank_name'],
                        'account_name' => $responseData['data']['account_name'],
                    ],
                ];
            case 'check_transaction_status':
                return [
                    'status' => $responseData['status'] === 'success' ? 'success' : 'failed',
                    'message' => $responseData['message'] ?? 'Transaction status retrieved successfully',
                    'data' => [
                        'transaction_reference' => $responseData['data']['transaction_reference'],
                        'status' => $responseData['data']['status'],
                        'amount' => $responseData['data']['amount'],
                        'currency' => $responseData['data']['currency'],
                    ],
                ];
            case 'verify_bank_account':
                return [
                    'status' => $responseData['status'] === 'success' ? 'success' : 'failed',
                    'message' => $responseData['message'] ?? 'Bank account verified successfully',
                    'data' => [
                        'account_number' => $responseData['data']['account_number'],
                        'account_name' => $responseData['data']['account_name'],
                        'bank_code' => $responseData['data']['bank_code'],
                    ],
                ];
            case 'transfer_funds':
                return [
                    'status' => $responseData['status'] === 'success' ? 'success' : 'failed',
                    'message' => $responseData['message'] ?? 'Funds transferred successfully',
                    'data' => [
                        'transfer_reference' => $responseData['data']['transfer_reference'],
                        'amount' => $responseData['data']['amount'],
                        'currency' => $responseData['data']['currency'],
                        'recipient' => $responseData['data']['recipient'],
                    ],
                ];
            case 'initiate_payment':
                return [
                    'status' => $responseData['status'] === 'success' ? 'success' : 'failed',
                    'message' => $responseData['message'] ?? 'Payment initiated successfully',
                    'data' => [
                        'payment_reference' => $responseData['data']['payment_reference'],
                        'amount' => $responseData['data']['amount'],
                        'currency' => $responseData['data']['currency'],
                    ],
                ];
            default:
                throw new \InvalidArgumentException("Unsupported action: {$action}");
        }
    }
    
    
}
