<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PaymentConfiguration extends Model
{
    use HasFactory;

    protected $table = 'payment_configurations';

    protected $fillable = [
        'collection_api_user',
        'collection_api_key',
        'collection_subscription_key',
        'disbursement_api_user',
        'disbursement_api_key',
        'disbursement_subscription_key',
        'environment',
        'currency',
        'service_type',
        'is_free',
        'amount_ssp',
        'amount_usd',
        'frequencies',
        'default_frequency',
        'grace_period_days',
        'description',
        'is_active',
    ];

    protected $casts = [
        'collection_api_user'           => 'encrypted',
        'collection_api_key'            => 'encrypted',
        'collection_subscription_key'   => 'encrypted',
        'disbursement_api_user'         => 'encrypted',
        'disbursement_api_key'          => 'encrypted',
        'disbursement_subscription_key' => 'encrypted',
        'is_free'           => 'boolean',
        'amount_ssp'        => 'decimal:2',
        'amount_usd'        => 'decimal:2',
        'frequencies'       => 'array',
        'grace_period_days' => 'integer',
        'is_active'         => 'boolean',
        'created_at'        => 'datetime',
        'updated_at'        => 'datetime',
    ];

    protected $hidden = [
        'collection_api_key',
        'collection_subscription_key',
        'disbursement_api_key',
        'disbursement_subscription_key',
    ];

    protected $attributes = [
        'is_free'           => false,
        'amount_ssp'        => 0,
        'default_frequency' => 'yearly',
        'grace_period_days' => 7,
        'is_active'         => true,
        'environment'       => 'sandbox',
        'currency'          => 'SSP',
    ];

    // =========================================================================
    // SCOPES
    // =========================================================================

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeForInstitutions($query)
    {
        return $query->where('service_type', 'institution');
    }

    public function scopeForMachines($query)
    {
        return $query->where('service_type', 'machine');
    }

    // =========================================================================
    // ACCESSORS
    // =========================================================================

    public function getFormattedSspPriceAttribute(): string
    {
        return 'SSP ' . number_format($this->amount_ssp ?? 0, 2);
    }

    public function getFormattedUsdPriceAttribute(): string
    {
        return $this->amount_usd ? '$' . number_format($this->amount_usd, 2) : 'Not Set';
    }

    public function getDefaultFrequencyLabelAttribute(): string
    {
        return match ($this->default_frequency) {
            'one_time'  => 'One-time',
            'monthly'   => 'Monthly',
            'quarterly' => 'Quarterly',
            'biannual'  => 'Bi-annual',
            'yearly'    => 'Yearly',
            default     => ucfirst($this->default_frequency ?? ''),
        };
    }

    public function getAvailableFrequenciesAttribute(): array
    {
        $all = self::getFrequencyOptions();
        if (empty($this->frequencies)) {
            return $all;
        }
        return array_intersect_key($all, array_flip($this->frequencies));
    }

    // =========================================================================
    // HELPER METHODS
    // =========================================================================

    public function requiresPayment(): bool
    {
        return !$this->is_free && ($this->amount_ssp > 0 || ($this->amount_usd && $this->amount_usd > 0));
    }

    public function getAmountForCurrency(string $currency = 'SSP'): float
    {
        if ($this->is_free) {
            return 0;
        }
        return match (strtoupper($currency)) {
            'USD'   => (float) ($this->amount_usd ?? 0),
            default => (float) ($this->amount_ssp ?? 0),
        };
    }

    public function calculateCoverageEnd(string $frequency = null, ?\Carbon\Carbon $startDate = null): \Carbon\Carbon
    {
        $frequency = $frequency ?? $this->default_frequency ?? 'yearly';
        $startDate = $startDate ?? now();

        return match ($frequency) {
            'one_time'  => $startDate->copy()->addYears(100),
            'monthly'   => $startDate->copy()->addMonth(),
            'quarterly' => $startDate->copy()->addMonths(3),
            'biannual'  => $startDate->copy()->addMonths(6),
            'yearly'    => $startDate->copy()->addYear(),
            default     => $startDate->copy()->addYear(),
        };
    }

    public function hasCollectionCredentials(): bool
    {
        return !empty($this->collection_api_user)
            && !empty($this->collection_api_key)
            && !empty($this->collection_subscription_key);
    }

    public function hasDisbursementCredentials(): bool
    {
        return !empty($this->disbursement_api_user)
            && !empty($this->disbursement_api_key)
            && !empty($this->disbursement_subscription_key);
    }

    public function isComplete(): bool
    {
        return $this->hasCollectionCredentials() || $this->hasDisbursementCredentials();
    }

    public function getBaseUrl(): string
    {
        return $this->environment === 'production'
            ? 'https://momodeveloper.mtn.com'
            : 'https://sandbox.momodeveloper.mtn.com';
    }

    public function getMaskedCredentials(): array
    {
        return [
            'collection_api_user'           => $this->maskValue($this->collection_api_user),
            'collection_subscription_key'   => $this->maskValue($this->collection_subscription_key),
            'disbursement_api_user'         => $this->maskValue($this->disbursement_api_user),
            'disbursement_subscription_key' => $this->maskValue($this->disbursement_subscription_key),
        ];
    }

    private function maskValue(?string $value): string
    {
        if (empty($value)) {
            return 'Not Configured';
        }
        $length = strlen($value);
        if ($length <= 8) {
            return str_repeat('*', $length);
        }
        return substr($value, 0, 4) . str_repeat('*', $length - 8) . substr($value, -4);
    }

    // =========================================================================
    // STATIC METHODS
    // =========================================================================

    public static function getActive(): ?self
    {
        return static::where('is_active', true)->whereNull('service_type')->first();
    }

    public static function getForInstitutions(): ?self
    {
        return static::active()->forInstitutions()->first();
    }

    public static function getForMachines(): ?self
    {
        return static::active()->forMachines()->first();
    }

    /** Alias used by InstitutionRegistrationController */
    public static function getInstitutionConfig(): ?self
    {
        return static::getForInstitutions();
    }

    public static function getFrequencyOptions(): array
    {
        return [
            'one_time'  => 'One-time Payment',
            'monthly'   => 'Monthly Subscription',
            'quarterly' => 'Quarterly Subscription',
            'biannual'  => 'Bi-annual Subscription',
            'yearly'    => 'Annual Subscription',
        ];
    }

    public static function getServiceTypes(): array
    {
        return [
            'institution' => 'Health Institution Listing',
            'machine'     => 'Digital Health Machine Marketing',
        ];
    }

    protected static function booted(): void
    {
        static::saving(function (self $config) {
            if ($config->is_active && empty($config->service_type)) {
                static::whereNull('service_type')
                    ->where('id', '!=', $config->id ?? 0)
                    ->where('is_active', true)
                    ->update(['is_active' => false]);
            }
        });
    }
}
