<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class PaymentProvider extends Model
{
    protected $fillable = [
        'name',
        'display_name',
        'description',
        'is_active',
        'configuration',
        'supports_recurring',
        'supports_one_time',
        'supported_currencies',
        'webhook_url',
        'webhook_secret',
        'fee_structure',
        'priority',
        'is_fallback',
    ];

    protected $casts = [
        'is_active' => 'boolean',
        'configuration' => 'encrypted:array',
        'supports_recurring' => 'boolean',
        'supports_one_time' => 'boolean',
        'supported_currencies' => 'array',
        'fee_structure' => 'array',
        'is_fallback' => 'boolean',
    ];

    /**
     * Scope to get only active providers
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope to get providers that support recurring payments
     */
    public function scopeRecurring($query)
    {
        return $query->where('supports_recurring', true);
    }

    /**
     * Scope to get providers that support one-time payments
     */
    public function scopeOneTime($query)
    {
        return $query->where('supports_one_time', true);
    }

    /**
     * Scope to get providers ordered by priority
     */
    public function scopeByPriority($query)
    {
        return $query->orderBy('priority', 'desc');
    }

    /**
     * Get the fallback provider
     */
    public static function getFallback()
    {
        return static::where('is_fallback', true)->active()->first();
    }

    /**
     * Check if provider supports a specific currency
     */
    public function supportsCurrency(string $currency): bool
    {
        return in_array(strtoupper($currency), $this->supported_currencies);
    }

    /**
     * Get fee for a specific amount
     */
    public function calculateFee(float $amount): array
    {
        if (! $this->fee_structure) {
            return [
                'fixed_fee' => 0,
                'percentage_fee' => 0,
                'total_fee' => 0,
                'net_amount' => $amount,
            ];
        }

        $fixedFee = $this->fee_structure['fixed_fee'] ?? 0;
        $percentageFee = $this->fee_structure['percentage_fee'] ?? 0;
        $percentageAmount = ($amount * $percentageFee) / 100;
        $totalFee = $fixedFee + $percentageAmount;

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

    /**
     * Get webhook endpoint URL
     */
    public function getWebhookUrl(): string
    {
        return $this->webhook_url ?? route('webhook.payment', $this->name);
    }

    /**
     * Update configuration
     */
    public function updateConfiguration(array $config): void
    {
        $this->configuration = array_merge($this->configuration ?? [], $config);
        $this->save();
    }

    /**
     * Get specific configuration value
     */
    public function getConfigValue(string $key, $default = null)
    {
        return data_get($this->configuration, $key, $default);
    }

    /**
     * Set specific configuration value
     */
    public function setConfigValue(string $key, $value): void
    {
        $config = $this->configuration ?? [];
        data_set($config, $key, $value);
        $this->configuration = $config;
        $this->save();
    }

    /**
     * Check if provider is properly configured
     */
    public function isConfigured(): bool
    {
        $requiredFields = $this->getConfigValue('required_fields', []);

        foreach ($requiredFields as $field) {
            if (empty($this->getConfigValue($field))) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get provider statistics
     */
    public function getStats(): array
    {
        $subscriptionCount = Subscription::where('provider', $this->name)->count();
        $activeSubscriptionCount = Subscription::where('provider', $this->name)
            ->where('unified_status', 'active')
            ->count();

        return [
            'name' => $this->name,
            'display_name' => $this->display_name,
            'is_active' => $this->is_active,
            'is_configured' => $this->isConfigured(),
            'total_subscriptions' => $subscriptionCount,
            'active_subscriptions' => $activeSubscriptionCount,
            'supports_recurring' => $this->supports_recurring,
            'supports_one_time' => $this->supports_one_time,
            'supported_currencies' => $this->supported_currencies,
            'is_fallback' => $this->is_fallback,
            'priority' => $this->priority,
        ];
    }

    /**
     * Activate provider
     */
    public function activate(): void
    {
        $this->is_active = true;
        $this->save();
    }

    /**
     * Deactivate provider
     */
    public function deactivate(): void
    {
        if ($this->is_fallback) {
            throw new \Exception('Cannot deactivate fallback provider');
        }

        $this->is_active = false;
        $this->save();
    }

    /**
     * Set as fallback provider
     */
    public function setAsFallback(): void
    {
        // Remove fallback status from other providers
        static::where('is_fallback', true)->update(['is_fallback' => false]);

        $this->is_fallback = true;
        $this->save();
    }

    /**
     * Remove fallback status
     */
    public function removeFallback(): void
    {
        $this->is_fallback = false;
        $this->save();
    }

    /**
     * Get provider class name
     */
    public function getProviderClass(): string
    {
        return $this->getConfigValue('class', '');
    }

    /**
     * Test provider connection
     */
    public function testConnection(): array
    {
        try {
            $class = $this->getProviderClass();

            if (! class_exists($class)) {
                return [
                    'success' => false,
                    'error' => "Provider class {$class} not found",
                ];
            }

            $provider = new $class($this->configuration);

            if (! $provider instanceof \App\Contracts\Payments\PaymentProviderContract) {
                return [
                    'success' => false,
                    'error' => 'Provider class does not implement PaymentProviderContract',
                ];
            }

            $isActive = $provider->isActive();

            return [
                'success' => true,
                'is_active' => $isActive,
                'configuration_valid' => $this->isConfigured(),
            ];

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

    /**
     * Get all active providers ordered by priority
     */
    public static function getActiveOrdered()
    {
        return static::active()->byPriority()->get();
    }

    /**
     * Get providers that support a specific plan type
     */
    public static function getForPlanType(bool $recurring = false)
    {
        $query = static::active();

        if ($recurring) {
            $query->recurring();
        } else {
            $query->oneTime();
        }

        return $query->byPriority()->get();
    }
}
