<?php

namespace App\Services\Payments\Gateways;

use App\Services\Payments\PaymentGatewayInterface;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
use Exception;

class NowPaymentsGateway implements PaymentGatewayInterface
{
    protected $apiKey;
    protected $baseUrl = 'https://api.nowpayments.io/v1';

    public function __construct($config, $mode)
    {
        // NOWPayments has no real sandbox. We enforce the LIVE credentials always.
        $this->apiKey = $config['live_credentials']['api_key'] ?? '';
    }

    public function pay(float $amount, string $currency, array $metadata)
    {
        if (empty($this->apiKey)) {
            throw new Exception("NOWPayments API Key is missing. Please add it in the Admin Panel.");
        }

        $orderNumber = $metadata['order_number'];

        $response = Http::withHeaders([
            'x-api-key' => $this->apiKey,
            'Content-Type' => 'application/json',
        ])->post("{$this->baseUrl}/invoice", [
            'price_amount' => $amount,
            'price_currency' => strtoupper($currency), // e.g., USDT or USD
            'order_id' => $orderNumber,
            'order_description' => 'Order #' . $orderNumber,
            // When user finishes or cancels, return back to system
            'success_url' => route('payment.callback', ['gateway' => 'nowpayments', 'order' => $orderNumber]),
            'cancel_url' => route('payment.callback', ['gateway' => 'nowpayments', 'order' => $orderNumber, 'cancel' => 1]),
        ]);

        if ($response->successful() && $response->json('invoice_url')) {
            // Cache the Invoice ID for 24 hours so we can verify it securely later
            Cache::put("nowpayments_{$orderNumber}", $response->json('id'), 86400); 

            return ['url' => $response->json('invoice_url')];
        }

        throw new Exception("NOWPayments Error: " . $response->body());
    }

    public function verify(array $requestData): array
    {
        $orderNumber = $requestData['order'] ?? null;
        $isCancelled = isset($requestData['cancel']);

        // User manually cancelled the payment
        if (!$orderNumber || $isCancelled) {
            return ['success' => false, 'order_number' => $orderNumber];
        }

        $invoiceId = Cache::get("nowpayments_{$orderNumber}");

        if (!$invoiceId) {
            return ['success' => false, 'order_number' => $orderNumber];
        }

        // Server-to-Server Verification (Secure)
        $response = Http::withHeaders([
            'x-api-key' => $this->apiKey,
        ])->get("{$this->baseUrl}/invoice/{$invoiceId}");

        if ($response->successful()) {
            $status = $response->json('payment_status'); 

            /*
             * NOWPayments Statuses:
             * 'finished', 'confirmed', 'sending' = Crypto payment is fully successful
             * 'waiting', 'confirming' = Crypto is sent but awaiting blockchain confirmations (Takes 5-30 mins)
             */
            if (in_array($status, ['finished', 'confirmed', 'sending', 'partially_paid'])) {
                Cache::forget("nowpayments_{$orderNumber}");
                return [
                    'success' => true,
                    'order_number' => $orderNumber,
                    'payment_status' => 'processing',
                    'message' => 'Crypto payment confirmed successfully!'
                ];
            } elseif (in_array($status, ['waiting', 'confirming'])) {
                // Return success so Laravel doesn't crash the redirect, 
                // but explicitly keep the status 'pending' with a custom flash message.
                return [
                    'success' => true,
                    'order_number' => $orderNumber,
                    'payment_status' => 'pending', 
                    'message' => 'Your payment is verifying on the blockchain. The order status will update to processing once fully confirmed.'
                ];
            }
        }

        return ['success' => false, 'order_number' => $orderNumber];
    }
}