<?php

namespace App\Http\Controllers;

use App\Models\ActivationKey;
use App\Services\Payments\PaymentConfigurationManager;
use App\Services\Payments\PaymentOrchestrator;
use App\Services\Payments\Providers\ActivationKeyProvider;
use App\Services\Payments\Providers\CryptoProvider;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;

class PaymentProviderController extends Controller
{
    public function __construct(
        private PaymentConfigurationManager $configManager,
        private PaymentOrchestrator $orchestrator
    ) {}

    /**
     * Get all payment providers and their status
     */
    public function index(): JsonResponse
    {
        try {
            $status = $this->configManager->getProviderStatus();
            $stats = $this->orchestrator->getRegistry()->getProviderStats();

            return response()->json([
                'providers' => $status,
                'statistics' => $stats,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'error' => 'Failed to retrieve provider status',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get specific provider details
     */
    public function show(string $provider): JsonResponse
    {
        try {
            $providerInstance = $this->orchestrator->getRegistry()->get($provider);
            $config = $this->configManager->getProviderConfig($provider);

            return response()->json([
                'provider' => $provider,
                'name' => $providerInstance->getName(),
                'active' => $providerInstance->isActive(),
                'configuration' => $this->configManager->sanitizeConfig($config),
                'capabilities' => [
                    'supports_recurring' => $providerInstance->supportsRecurring(),
                    'supports_one_time' => $providerInstance->supportsOneTime(),
                    'supported_currencies' => $providerInstance->getSupportedCurrencies(),
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'error' => 'Provider not found',
                'message' => $e->getMessage(),
            ], 404);
        }
    }

    /**
     * Test provider connectivity
     */
    public function test(string $provider): JsonResponse
    {
        try {
            $result = $this->configManager->testProviderConnectivity($provider);

            return response()->json($result);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Failed to test provider',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Enable/disable a provider
     */
    public function toggle(Request $request, string $provider): JsonResponse
    {
        $validated = $request->validate([
            'enabled' => 'required|boolean',
        ]);

        try {
            $result = $this->configManager->toggleProvider($provider, $validated['enabled']);

            if ($result) {
                return response()->json([
                    'success' => true,
                    'message' => "Provider {$provider} has been ".
                        ($validated['enabled'] ? 'enabled' : 'disabled'),
                ]);
            }

            return response()->json([
                'success' => false,
                'message' => "Failed to toggle provider {$provider}",
            ], 400);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Failed to toggle provider',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Update provider configuration
     */
    public function updateConfig(Request $request, string $provider): JsonResponse
    {
        $config = $request->all();

        // Validate configuration
        $validation = $this->configManager->validateProviderConfig($provider, $config);
        if (! $validation['valid']) {
            throw ValidationException::withMessages([
                'config' => $validation['errors'],
            ]);
        }

        try {
            $this->configManager->updateProviderConfig($provider, $config);

            return response()->json([
                'success' => true,
                'message' => "Configuration updated for provider {$provider}",
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Failed to update configuration',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Refresh provider configurations
     */
    public function refresh(): JsonResponse
    {
        try {
            $this->configManager->refreshConfigurations();

            return response()->json([
                'success' => true,
                'message' => 'Provider configurations refreshed',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Failed to refresh configurations',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Redeem an activation key
     */
    public function redeemActivationKey(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'activation_key' => 'required|string',
        ]);

        try {
            $user = $request->user();
            if (! $user) {
                return response()->json([
                    'success' => false,
                    'error' => 'Authentication required',
                ], 401);
            }

            $provider = new ActivationKeyProvider;
            $result = $provider->redeemActivationKey($validated['activation_key'], $user);

            return response()->json([
                'success' => true,
                'data' => $result,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Failed to redeem activation key',
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * Validate an activation key
     */
    public function validateActivationKey(string $key): JsonResponse
    {
        try {
            $activationKey = ActivationKey::where('activation_key', $key)->first();

            if (! $activationKey) {
                return response()->json([
                    'valid' => false,
                    'reason' => 'Activation key not found',
                ]);
            }

            return response()->json([
                'valid' => true,
                'is_activated' => $activationKey->is_activated,
                'created_at' => $activationKey->created_at,
                'plan_id' => $activationKey->price_id,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'valid' => false,
                'error' => 'Failed to validate activation key',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get cryptocurrency exchange rate
     */
    public function getCryptoRate(string $crypto): JsonResponse
    {
        try {
            $provider = new CryptoProvider;

            // Test conversion with $1 USD to get rate
            $amount = $provider->convertUsdToCrypto(1.00, strtoupper($crypto));
            $rate = 1 / $amount; // Invert to get USD per crypto

            return response()->json([
                'crypto' => strtoupper($crypto),
                'rate_usd_per_crypto' => $rate,
                'rate_crypto_per_usd' => $amount,
                'updated_at' => now()->toISOString(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'error' => 'Failed to get crypto rate',
                'message' => $e->getMessage(),
            ], 400);
        }
    }

    /**
     * Convert USD to cryptocurrency
     */
    public function convertUsdToCrypto(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'usd_amount' => 'required|numeric|min:0.01',
            'crypto' => 'required|string|in:BTC,ETH,USDT,USDC,LTC',
        ]);

        try {
            $provider = new CryptoProvider;
            $cryptoAmount = $provider->convertUsdToCrypto(
                $validated['usd_amount'],
                strtoupper($validated['crypto'])
            );

            $fees = $provider->calculateFees($validated['usd_amount']);

            return response()->json([
                'usd_amount' => $validated['usd_amount'],
                'crypto' => strtoupper($validated['crypto']),
                'crypto_amount' => $cryptoAmount,
                'fees' => $fees,
                'net_crypto_amount' => $cryptoAmount, // Crypto providers typically don't deduct fees from amount
                'updated_at' => now()->toISOString(),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'error' => 'Failed to convert USD to crypto',
                'message' => $e->getMessage(),
            ], 400);
        }
    }
}
