<?php

namespace App\Services\Payments\Providers;

use App\Contracts\Payments\PaymentProviderContract;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class OxapayProvider implements PaymentProviderContract
{
    protected array $config;

    protected string $baseUrl;

    public function __construct(array $config = [])
    {
        $this->config = $config;
        $this->baseUrl = $config['sandbox'] ?? false
            ? 'https://api-sandbox.oxapay.com/v1'
            : 'https://api.oxapay.com/v1';
    }

    public function getName(): string
    {
        return 'oxapay';
    }

    public function isActive(): bool
    {
        return ! empty($this->config['merchant_api_key']);
    }

    public function supportsRecurring(): bool
    {
        return false; // OxaPay doesn't support recurring payments
    }

    public function supportsOneTime(): bool
    {
        return true;
    }

    public function getSupportedCurrencies(): array
    {
        return Cache::remember('oxapay_currencies', now()->addHour(), function () {
            try {
                $response = Http::withHeaders([
                    'merchant_api_key' => $this->config['merchant_api_key'],
                ])->get("{$this->baseUrl}/info/currencies");

                if ($response->successful()) {
                    $data = $response->json();

                    return $data['data'] ?? [];
                }
            } catch (\Exception $e) {
                Log::error('Failed to fetch OxaPay currencies', [
                    'error' => $e->getMessage(),
                ]);
            }

            return ['BTC', 'ETH', 'USDT', 'USDC', 'LTC', 'BCH']; // Default common cryptos
        });
    }

    public function calculateFees(float $amount): array
    {
        // OxaPay fees vary by currency and network
        // Using average estimates - actual fees should be fetched from API
        $percentageFee = 0.5; // 0.5% average
        $fixedFee = 0.0; // No fixed fee for most cryptos
        $totalFee = ($amount * $percentageFee / 100) + $fixedFee;

        return [
            'fixed_fee' => $fixedFee,
            'percentage_fee' => $percentageFee,
            'total_fee' => $totalFee,
            'net_amount' => $amount - $totalFee,
        ];
    }

    public function createSubscription(User $user, Plan $plan, array $options = []): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function cancelSubscription(Subscription $subscription, string $reason = ''): bool
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function updateSubscription(Subscription $subscription, Plan $newPlan): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function pauseSubscription(Subscription $subscription): bool
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function resumeSubscription(Subscription $subscription): bool
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function getSubscriptionDetails(string $subscriptionId): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function createCheckoutSession(User $user, Plan $plan, array $options = []): array
    {
        try {
            $amount = $options['amount'] ?? $plan->price;
            $currency = $options['currency'] ?? 'USD';
            $toCurrency = $options['to_currency'] ?? 'USDT';

            $payload = [
                'amount' => $amount,
                'currency' => $currency,
                'to_currency' => $toCurrency,
                'lifetime' => $options['lifetime'] ?? 60, // 60 minutes default
                'fee_paid_by_payer' => $options['fee_paid_by_payer'] ?? 0,
                'callback_url' => $this->config['webhook_url'] ?? route('webhooks.oxapay'),
                'return_url' => $this->config['success_url'] ?? route('payment.success'),
                'email' => $user->email,
                'order_id' => $options['order_id'] ?? null,
                'description' => $options['description'] ?? "Payment for {$plan->name}",
                'sandbox' => $this->config['sandbox'] ?? false,
            ];

            $response = Http::withHeaders([
                'merchant_api_key' => $this->config['merchant_api_key'],
                'Content-Type' => 'application/json',
            ])->post("{$this->baseUrl}/payment/invoice", $payload);

            if (! $response->successful()) {
                throw new \Exception('Failed to create OxaPay invoice: '.$response->body());
            }

            $data = $response->json();

            return [
                'success' => true,
                'checkout_url' => $data['data']['payment_url'] ?? null,
                'payment_id' => $data['data']['track_id'] ?? null,
                'expires_at' => $data['data']['expired_at'] ?? null,
                'amount' => $amount,
                'currency' => $currency,
                'provider' => 'oxapay',
            ];

        } catch (\Exception $e) {
            Log::error('OxaPay checkout session creation failed', [
                'error' => $e->getMessage(),
                'user_id' => $user->id,
                'plan_id' => $plan->id,
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    public function createCustomerPortalSession(User $user): array
    {
        throw new \Exception('OxaPay does not provide customer portal functionality');
    }

    public function processWebhook(Request $request): array
    {
        try {
            $payload = $request->getContent();
            $signature = $request->header('HMAC');

            if (! $this->validateWebhook($request)) {
                throw new \Exception('Invalid webhook signature');
            }

            $data = $request->json()->all();
            $status = $data['status'] ?? 'unknown';
            $trackId = $data['track_id'] ?? null;
            $type = $data['type'] ?? 'payment';

            return [
                'success' => true,
                'event_type' => $status,
                'provider_transaction_id' => $trackId,
                'processed' => true,
                'data' => $data,
                'type' => $type,
            ];

        } catch (\Exception $e) {
            Log::error('OxaPay webhook processing failed', [
                'error' => $e->getMessage(),
                'payload' => $request->getContent(),
            ]);

            return [
                'success' => false,
                'event_type' => 'error',
                'provider_transaction_id' => null,
                'processed' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    public function validateWebhook(Request $request): bool
    {
        try {
            $payload = $request->getContent();
            $signature = $request->header('HMAC');
            $apiSecret = $this->config['merchant_api_key'];

            if (empty($signature) || empty($apiSecret)) {
                return false;
            }

            $expectedSignature = hash_hmac('sha512', $payload, $apiSecret);

            return hash_equals($expectedSignature, $signature);

        } catch (\Exception $e) {
            Log::error('OxaPay webhook validation failed', [
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    public function getConfiguration(): array
    {
        return $this->config;
    }

    public function syncSubscriptionStatus(Subscription $subscription): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function getPaymentMethodDetails(string $paymentId): array
    {
        try {
            $response = Http::withHeaders([
                'merchant_api_key' => $this->config['merchant_api_key'],
            ])->get("{$this->baseUrl}/payment/info", [
                'track_id' => $paymentId,
            ]);

            if ($response->successful()) {
                $data = $response->json();

                return [
                    'success' => true,
                    'details' => $data['data'] ?? [],
                ];
            }

            return [
                'success' => false,
                'error' => 'Payment not found',
            ];

        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    public function processRefund(string $paymentIntentId, float $amount, string $reason = ''): array
    {
        // OxaPay doesn't support traditional refunds in crypto
        // Would need manual payout process
        return [
            'success' => false,
            'error' => 'OxaPay refunds must be processed manually via payouts',
        ];
    }

    public function getTransactionHistory(User $user, array $filters = []): array
    {
        try {
            $response = Http::withHeaders([
                'merchant_api_key' => $this->config['merchant_api_key'],
            ])->get("{$this->baseUrl}/payment/history", array_merge([
                'email' => $user->email,
            ], $filters));

            if ($response->successful()) {
                $data = $response->json();

                return [
                    'success' => true,
                    'transactions' => $data['data'] ?? [],
                ];
            }

            return [
                'success' => false,
                'error' => 'Failed to fetch transaction history',
            ];

        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    public function getSubscriptionMetadata(Subscription $subscription): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function updateSubscriptionMetadata(Subscription $subscription, array $metadata): bool
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function startTrial(Subscription $subscription, int $trialDays): bool
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function applyCoupon(Subscription $subscription, string $couponCode): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function removeCoupon(Subscription $subscription): bool
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function getUpcomingInvoice(Subscription $subscription): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function retryFailedPayment(Subscription $subscription): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function canModifySubscription(Subscription $subscription): bool
    {
        return false; // No recurring support
    }

    public function getCancellationTerms(Subscription $subscription): array
    {
        return [
            'immediate_cancellation' => true,
            'refund_policy' => 'no_refunds_crypto',
            'cancellation_effective' => 'immediately',
            'billing_cycle_proration' => false,
        ];
    }

    public function exportSubscriptionData(Subscription $subscription): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }

    public function importSubscriptionData(User $user, array $subscriptionData): array
    {
        throw new \Exception('OxaPay does not support recurring subscriptions');
    }
}
