<?php

namespace App\Services;

use App\Models\PaymentConfiguration;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

/**
 * PaymentConfigurationService
 *
 * Manages CRUD operations for MTN MoMo payment credentials with encryption and caching.
 */
class PaymentConfigurationService
{
    protected string $cacheKey = 'payment_configuration_active';
    protected int $cacheTtl = 3600;

    public function getConfiguration(): ?PaymentConfiguration
    {
        try {
            return Cache::remember($this->cacheKey, $this->cacheTtl, function () {
                return PaymentConfiguration::getActive();
            });
        } catch (\Exception $e) {
            Log::error('Failed to retrieve payment configuration', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return null;
        }
    }

    public function saveConfiguration(array $data): PaymentConfiguration
    {
        try {
            $configuration = $this->getConfiguration();

            if ($configuration) {
                $configuration->update([
                    'collection_api_user'          => $data['collection_api_user']          ?? $configuration->collection_api_user,
                    'collection_api_key'           => $data['collection_api_key']           ?? $configuration->collection_api_key,
                    'collection_subscription_key'  => $data['collection_subscription_key']  ?? $configuration->collection_subscription_key,
                    'disbursement_api_user'        => $data['disbursement_api_user']        ?? $configuration->disbursement_api_user,
                    'disbursement_api_key'         => $data['disbursement_api_key']         ?? $configuration->disbursement_api_key,
                    'disbursement_subscription_key' => $data['disbursement_subscription_key'] ?? $configuration->disbursement_subscription_key,
                    'environment'                  => $data['environment']                  ?? $configuration->environment,
                    'currency'                     => $data['currency']                     ?? $configuration->currency,
                    'is_active'                    => true,
                ]);
            } else {
                $configuration = PaymentConfiguration::create([
                    'collection_api_user'          => $data['collection_api_user']          ?? null,
                    'collection_api_key'           => $data['collection_api_key']           ?? null,
                    'collection_subscription_key'  => $data['collection_subscription_key']  ?? null,
                    'disbursement_api_user'        => $data['disbursement_api_user']        ?? null,
                    'disbursement_api_key'         => $data['disbursement_api_key']         ?? null,
                    'disbursement_subscription_key' => $data['disbursement_subscription_key'] ?? null,
                    'environment'                  => $data['environment']                  ?? 'sandbox',
                    'currency'                     => $data['currency']                     ?? 'SSP',
                    'is_active'                    => true,
                ]);
            }

            $this->clearCache();

            Log::info('Payment configuration saved successfully', [
                'environment'      => $configuration->environment,
                'has_collection'   => $configuration->hasCollectionCredentials(),
                'has_disbursement' => $configuration->hasDisbursementCredentials(),
            ]);

            return $configuration;

        } catch (\Exception $e) {
            Log::error('Failed to save payment configuration', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            throw $e;
        }
    }

    public function deleteConfiguration(): bool
    {
        try {
            $configuration = $this->getConfiguration();

            if (!$configuration) {
                return false;
            }

            $deleted = $configuration->delete();
            $this->clearCache();

            Log::info('Payment configuration deleted successfully');

            return $deleted;

        } catch (\Exception $e) {
            Log::error('Failed to delete payment configuration', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            throw $e;
        }
    }

    public function isConfigured(): bool
    {
        $configuration = $this->getConfiguration();
        if ($configuration && $configuration->isComplete()) {
            return true;
        }
        // Fallback: env vars are sufficient
        return !empty(config('services.mtn_momo.api_user'))
            && !empty(config('services.mtn_momo.api_key'))
            && !empty(config('services.mtn_momo.subscription_key'));
    }

    public function hasCollectionCredentials(): bool
    {
        $configuration = $this->getConfiguration();
        if ($configuration && $configuration->hasCollectionCredentials()) {
            return true;
        }
        // Fallback to env vars
        return !empty(config('services.mtn_momo.api_user'))
            && !empty(config('services.mtn_momo.api_key'))
            && !empty(config('services.mtn_momo.subscription_key'));
    }

    public function hasDisbursementCredentials(): bool
    {
        $configuration = $this->getConfiguration();
        return $configuration && $configuration->hasDisbursementCredentials();
    }

    public function getCollectionCredentials(): ?array
    {
        $configuration = $this->getConfiguration();

        if ($configuration && $configuration->hasCollectionCredentials()) {
            return [
                'api_user'         => $configuration->collection_api_user,
                'api_key'          => $configuration->collection_api_key,
                'subscription_key' => $configuration->collection_subscription_key,
            ];
        }

        // Fallback to env vars via config
        $apiUser = config('services.mtn_momo.api_user');
        $apiKey  = config('services.mtn_momo.api_key');
        $subKey  = config('services.mtn_momo.subscription_key');

        if ($apiUser && $apiKey && $subKey) {
            return [
                'api_user'         => $apiUser,
                'api_key'          => $apiKey,
                'subscription_key' => $subKey,
            ];
        }

        return null;
    }

    public function getDisbursementCredentials(): ?array
    {
        $configuration = $this->getConfiguration();

        if (!$configuration || !$configuration->hasDisbursementCredentials()) {
            return null;
        }

        return [
            'api_user'         => $configuration->disbursement_api_user,
            'api_key'          => $configuration->disbursement_api_key,
            'subscription_key' => $configuration->disbursement_subscription_key,
        ];
    }

    public function getEnvironment(): string
    {
        $configuration = $this->getConfiguration();
        return $configuration?->environment ?? config('services.mtn_momo.environment', 'sandbox');
    }

    public function getBaseUrl(): string
    {
        $env = $this->getEnvironment();
        return config('services.mtn_momo.base_url',
            $env === 'production'
                ? 'https://momodeveloper.mtn.com'
                : 'https://sandbox.momodeveloper.mtn.com'
        );
    }

    public function getMaskedConfiguration(): array
    {
        $configuration = $this->getConfiguration();

        if (!$configuration) {
            return [
                'exists'          => false,
                'environment'     => 'sandbox',
                'has_collection'  => false,
                'has_disbursement' => false,
            ];
        }

        return array_merge(
            ['exists' => true],
            $configuration->getMaskedCredentials(),
            [
                'environment'     => $configuration->environment,
                'currency'        => $configuration->currency ?? 'SSP',
                'is_active'       => $configuration->is_active,
                'has_collection'  => $configuration->hasCollectionCredentials(),
                'has_disbursement' => $configuration->hasDisbursementCredentials(),
                'updated_at'      => $configuration->updated_at?->format('Y-m-d H:i:s'),
            ]
        );
    }

    public function clearCache(): void
    {
        Cache::forget($this->cacheKey);
    }

    public function getStatusSummary(): array
    {
        return [
            'is_configured'   => $this->isConfigured(),
            'environment'     => $this->getEnvironment(),
            'currency'        => $this->getCurrency(),
            'has_collection'  => $this->hasCollectionCredentials(),
            'has_disbursement' => $this->hasDisbursementCredentials(),
            'last_updated'    => $this->getConfiguration()?->updated_at?->diffForHumans() ?? 'Never',
        ];
    }

    public function getCurrency(): string
    {
        $configuration = $this->getConfiguration();
        return $configuration?->currency ?? config('services.mtn_momo.currency', 'SSP');
    }
}
