<?php

namespace App\Modules\ProviderIntegration\Services;

use App\Core\Exceptions\ProviderException;
use App\Modules\ProviderIntegration\Interfaces\ProviderInterface;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class VTPassProvider implements ProviderInterface
{
    protected string $baseUrl;
    protected string $apiKey;
    protected string $secretKey;
    protected string $publicKey;
    protected int $timeout;

    public function __construct()
    {
        $isSandbox = config('services.vtpass.sandbox', false);

        if ($isSandbox) {
            $this->baseUrl = config('services.vtpass.sandbox_url');
            $this->apiKey = config('services.vtpass.sandbox_api_key');
            $this->secretKey = config('services.vtpass.sandbox_secret_key');
            $this->publicKey = config('services.vtpass.sandbox_public_key');
        } else {
            $this->baseUrl = config('services.vtpass.base_url');
            $this->apiKey = config('services.vtpass.api_key');
            $this->secretKey = config('services.vtpass.secret_key');
            $this->publicKey = config('services.vtpass.public_key');
        }

        $this->timeout = config('services.vtpass.timeout', 30);
    }

    protected function postHeaders(): array
    {
        return [
            'api-key' => $this->apiKey,
            'secret-key' => $this->secretKey,
            'Content-Type' => 'application/json',
        ];
    }

    protected function getHeaders(): array
    {
        return [
            'api-key' => $this->apiKey,
            'public-key' => $this->publicKey,
            'Content-Type' => 'application/json',
        ];
    }

    protected function post(string $endpoint, array $data = []): array
    {
        try {
            $response = Http::timeout($this->timeout)
                ->withHeaders($this->postHeaders())
                ->post("{$this->baseUrl}/{$endpoint}", $data);

            $body = $response->json();

            Log::info('VTPass API Response', [
                'endpoint' => $endpoint,
                'status' => $response->status(),
                'response' => $body,
            ]);

            if ($response->failed()) {
                throw new ProviderException('vtpass', $body['response_description'] ?? $body['message'] ?? 'Request failed');
            }

            $code = $body['code'] ?? $body['response_description'] ?? null;
            if ($code && $code !== '000') {
                throw new ProviderException('vtpass', $body['response_description'] ?? $body['message'] ?? 'VTPass error: ' . $code);
            }

            return $body;
        } catch (ProviderException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('VTPass API Error', [
                'endpoint' => $endpoint,
                'error' => $e->getMessage(),
            ]);
            throw new ProviderException('vtpass', 'Unable to connect to VTPass: ' . $e->getMessage());
        }
    }

    protected function get(string $endpoint, array $params = []): array
    {
        try {
            $response = Http::timeout($this->timeout)
                ->withHeaders($this->getHeaders())
                ->get("{$this->baseUrl}/{$endpoint}", $params);

            $body = $response->json();

            Log::info('VTPass API Response', [
                'endpoint' => $endpoint,
                'status' => $response->status(),
                'response' => $body,
            ]);

            if ($response->failed()) {
                throw new ProviderException('vtpass', $body['response_description'] ?? $body['message'] ?? 'Request failed');
            }

            $code = $body['code'] ?? $body['response_description'] ?? null;
            if ($code && $code !== '000') {
                throw new ProviderException('vtpass', $body['response_description'] ?? $body['message'] ?? 'VTPass error: ' . $code);
            }

            return $body;
        } catch (ProviderException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('VTPass API Error', [
                'endpoint' => $endpoint,
                'error' => $e->getMessage(),
            ]);
            throw new ProviderException('vtpass', 'Unable to connect to VTPass: ' . $e->getMessage());
        }
    }

    public function generateRequestId(): string
    {
        $datePart = now('Africa/Lagos')->format('YmdHi');
        $suffix = strtoupper(bin2hex(random_bytes(4)));

        return $datePart . $suffix;
    }

    public function getServiceCategories(): array
    {
        return $this->get('service-categories');
    }

    public function getServices(string $category = ''): array
    {
        $params = $category ? ['identifier' => $category] : [];
        return $this->get('services', $params);
    }

    public function getVariations(string $serviceCode): array
    {
        return $this->get('service-variations', ['serviceID' => $serviceCode]);
    }

    public function validateCustomer(string $serviceCode, string $billersCode, string $type = ''): array
    {
        $data = [
            'billersCode' => $billersCode,
            'serviceID' => $serviceCode,
        ];

        if ($type !== '') {
            $data['type'] = $type;
        }

        return $this->post('merchant-verify', $data);
    }

    public function purchaseAirtime(
        string $phone,
        string $serviceID,
        float $amount,
        string $requestId
    ): array {
        return $this->post('pay', [
            'request_id' => $requestId,
            'serviceID' => $serviceID,
            'amount' => $amount,
            'phone' => $phone,
        ]);
    }

    public function purchaseData(
        string $phone,
        string $serviceID,
        string $variationCode,
        string $requestId
    ): array {
        return $this->post('pay', [
            'request_id' => $requestId,
            'serviceID' => $serviceID,
            'billersCode' => $phone,
            'variation_code' => $variationCode,
            'phone' => $phone,
        ]);
    }

    public function purchaseElectricity(
        string $meterNumber,
        string $serviceID,
        string $variationCode,
        float $amount,
        string $phone,
        string $requestId
    ): array {
        return $this->post('pay', [
            'request_id' => $requestId,
            'serviceID' => $serviceID,
            'billersCode' => $meterNumber,
            'variation_code' => $variationCode,
            'amount' => $amount,
            'phone' => $phone,
        ]);
    }

    public function purchaseCable(
        string $smartcardNumber,
        string $serviceID,
        string $variationCode,
        string $subscriptionType,
        float $amount,
        string $phone,
        string $requestId
    ): array {
        return $this->post('pay', [
            'request_id' => $requestId,
            'serviceID' => $serviceID,
            'billersCode' => $smartcardNumber,
            'variation_code' => $variationCode,
            'subscription_type' => $subscriptionType,
            'amount' => $amount,
            'phone' => $phone,
        ]);
    }

    public function purchaseExamPin(
        string $serviceID,
        string $variationCode,
        string $billersCode,
        string $phone,
        int $quantity,
        string $requestId
    ): array {
        return $this->post('pay', [
            'request_id' => $requestId,
            'serviceID' => $serviceID,
            'variation_code' => $variationCode,
            'billersCode' => $billersCode,
            'quantity' => $quantity,
            'phone' => $phone,
        ]);
    }

    public function queryTransactionStatus(string $requestId): array
    {
        return $this->post('requery', [
            'request_id' => $requestId,
        ]);
    }

    public function requeryTransaction(string $requestId): array
    {
        return $this->queryTransactionStatus($requestId);
    }
}
