<?php

namespace Licenzo\Model;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

use Licenzo\Casts\MoneyCast;
use Licenzo\Framework\Database\Model;

class SubscriptionTransaction extends Model
{
    protected $table = 'licenzo_subscription_transactions';

    // Transaction type constants
    const TYPE_CHARGE = 'charge';
    const TYPE_REFUND = 'refund';
    const TYPE_PURCHASE = 'purchase';
    const TYPE_RENEWAL = 'renewal';
    const TYPE_UPGRADE = 'upgrade';
    const TYPE_DOWNGRADE = 'downgrade';

    // Status constants
    const STATUS_SUCCESS = 'success';
    const STATUS_FAILED = 'failed';
    const STATUS_PENDING = 'pending';
    const STATUS_REFUNDED = 'refunded';

    // Provider constants
    const PROVIDER_STRIPE = 'stripe';
    const PROVIDER_PAYPAL = 'paypal';
    const PROVIDER_WOOCOMMERCE = 'woocommerce';
    const PROVIDER_EDD = 'edd';
    const PROVIDER_MANUAL = 'manual';

    // Payment method constants
    const PAYMENT_METHOD_CARD = 'card';
    const PAYMENT_METHOD_BANK_ACCOUNT = 'bank_account';
    const PAYMENT_METHOD_PAYPAL = 'paypal';

    // Payment mode constants
    const PAYMENT_MODE_LIVE = 'live';
    const PAYMENT_MODE_TEST = 'test';

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            $model->status = static::normalizeStatus($model->status ?? null);
        });

        static::updating(function ($model) {
            $model->status = static::normalizeStatus($model->status ?? null);
        });
    }

    protected $fillable = [
        'provider', 'provider_id', 'provider_charge_id', 'order_id', 'order_type',
        'transaction_type', 'subscription_id', 'customer_id',
        'card_last_4', 'card_brand', 'payment_method', 'payment_mode', 'payment_method_type',
        'status', 'currency', 'total', 'rate', 'uuid', 'meta',
        'description', 'failure_reason', 'failure_code', 'refund_reason',
        'invoice_url', 'receipt_url'
    ];

    protected $casts = [
        'id' => 'int',
        'provider_id' => 'int',
        'order_id' => 'int',
        'subscription_id' => 'int',
        'customer_id' => 'int',
        'total' => MoneyCast::class,
        'rate' => 'float',
        'meta' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

    // Relationships
    public function subscription()
    {
        return $this->belongsTo(Subscription::class);
    }

    public function customer()
    {
        return $this->belongsTo(Customer::class);
    }

    public function invoice()
    {
        return $this->belongsTo(Invoice::class, 'invoice_id');
    }

    // Scopes
    public function scopeCharges($query)
    {
        return $query->where('transaction_type', static::TYPE_CHARGE);
    }

    public function scopeRefunds($query)
    {
        return $query->where('transaction_type', static::TYPE_REFUND);
    }

    public function scopePurchases($query)
    {
        return $query->where('transaction_type', static::TYPE_PURCHASE);
    }

    public function scopeRenewals($query)
    {
        return $query->where('transaction_type', static::TYPE_RENEWAL);
    }

    public function scopeUpgrades($query)
    {
        return $query->where('transaction_type', static::TYPE_UPGRADE);
    }

    public function scopeDowngrades($query)
    {
        return $query->where('transaction_type', static::TYPE_DOWNGRADE);
    }

    public function scopeSuccessful($query)
    {
        return $query->where('status', static::STATUS_SUCCESS);
    }

    public function scopeFailed($query)
    {
        return $query->where('status', static::STATUS_FAILED);
    }

    public function scopePending($query)
    {
        return $query->where('status', static::STATUS_PENDING);
    }

    public function scopeRefunded($query)
    {
        return $query->where('status', static::STATUS_REFUNDED);
    }

    public function scopeByProvider($query, $provider)
    {
        return $query->where('provider', $provider);
    }

    // Helpers
    public function isCharge(): bool
    {
        return in_array($this->transaction_type, [
            static::TYPE_CHARGE,
            static::TYPE_PURCHASE,
            static::TYPE_RENEWAL,
            static::TYPE_UPGRADE,
            static::TYPE_DOWNGRADE
        ]);
    }

    public function isRefund(): bool
    {
        return $this->transaction_type === static::TYPE_REFUND;
    }

    public function isSuccessful(): bool
    {
        return $this->status === static::STATUS_SUCCESS;
    }

    public function isFailed(): bool
    {
        return $this->status === static::STATUS_FAILED;
    }

    public function isPending(): bool
    {
        return $this->status === static::STATUS_PENDING;
    }

    public function isRefunded(): bool
    {
        return $this->status === static::STATUS_REFUNDED;
    }

    public function getFormattedAmount(): string
    {
        $decimals = MoneyCast::minorUnits($this->currency ?? 'USD');

        return number_format($this->total, $decimals) . ' ' . strtoupper($this->currency ?? 'USD');
    }

    public static function normalizeStatus(?string $status): string
    {
        $normalized = strtolower(trim((string) $status));

        if (in_array($normalized, [
            static::STATUS_SUCCESS,
            static::STATUS_FAILED,
            static::STATUS_PENDING,
            static::STATUS_REFUNDED
        ], true)) {
            return $normalized;
        }

        return static::STATUS_PENDING;
    }
}
