<?php

namespace App\Libraries;

final class FinancialStatus
{
    public const INVOICE_UNPAID = 'unpaid';
    public const INVOICE_PARTIALLY_PAID = 'partially_paid';
    public const INVOICE_PAID = 'paid';
    public const INVOICE_OVERPAID = 'overpaid';
    public const INVOICE_CANCELLED = 'cancelled';

    public const PAYMENT_RECORDED = 'recorded';
    public const PAYMENT_VOIDED = 'voided';
    public const PAYMENT_FAILED = 'failed';
    public const PAYMENT_REFUNDED = 'refunded';
    public const PAYMENT_CHARGEBACK = 'chargeback';
    public const PAYMENT_DECLINED = 'declined';
    public const PAYMENT_REVERSED = 'reversed';
    public const PAYMENT_CANCELED = 'canceled';
    public const PAYMENT_CANCELLED = 'cancelled';

    public const PAYMENT_TRANSACTION_STATUSES = [
        self::PAYMENT_RECORDED,
        self::PAYMENT_VOIDED,
        self::PAYMENT_REFUNDED,
        self::PAYMENT_FAILED,
        self::PAYMENT_REVERSED,
        self::PAYMENT_CHARGEBACK,
    ];

    public const INVOICE_STATUSES = [
        self::INVOICE_UNPAID,
        self::INVOICE_PARTIALLY_PAID,
        self::INVOICE_PAID,
        self::INVOICE_OVERPAID,
        self::INVOICE_CANCELLED,
    ];

    public const REFUND_PENDING = 'pending';
    public const REFUND_APPROVED = 'approved';
    public const REFUND_REJECTED = 'rejected';
    public const REFUND_PARTIALLY_PAID = 'partially_paid';
    public const REFUND_PAID = 'paid';
    public const REFUND_VOIDED = 'voided';

    public const ADDITIONAL_CHARGE_PENDING = 'pending';
    public const ADDITIONAL_CHARGE_APPLIED = 'applied';
    public const ADDITIONAL_CHARGE_VOIDED = 'voided';

    public const EXCLUDED_PAYMENT_STATUSES = [
        self::PAYMENT_VOIDED,
        self::PAYMENT_FAILED,
        self::PAYMENT_REFUNDED,
        self::PAYMENT_CHARGEBACK,
        self::PAYMENT_DECLINED,
        self::PAYMENT_REVERSED,
        self::PAYMENT_CANCELED,
        self::PAYMENT_CANCELLED,
        'void',
    ];

    public const REFUND_REDUCES_INVOICE_STATUSES = [
        self::REFUND_PARTIALLY_PAID,
        self::REFUND_PAID,
        'partial',
        'paid',
        'Partial',
        'Paid',
    ];

    public static function normalizeInvoiceStatus(?string $status): string
    {
        return match (self::normalize($status)) {
            'paid', 'full' => self::INVOICE_PAID,
            'partially paid', 'partially_paid', 'partial' => self::INVOICE_PARTIALLY_PAID,
            'overpaid' => self::INVOICE_OVERPAID,
            'cancelled', 'canceled', 'cancelled invoice', 'canceled invoice' => self::INVOICE_CANCELLED,
            default => self::INVOICE_UNPAID,
        };
    }

    public static function normalizePaymentStatus(?string $status): string
    {
        return match (self::normalize($status)) {
            'completed', 'paid', 'full', 'recorded' => self::PAYMENT_RECORDED,
            'void', 'voided' => self::PAYMENT_VOIDED,
            'failed' => self::PAYMENT_FAILED,
            'refunded' => self::PAYMENT_REFUNDED,
            'chargeback' => self::PAYMENT_CHARGEBACK,
            'declined' => self::PAYMENT_DECLINED,
            'reversed' => self::PAYMENT_REVERSED,
            'cancelled' => self::PAYMENT_CANCELLED,
            'canceled' => self::PAYMENT_CANCELED,
            default => self::normalize($status),
        };
    }

    public static function normalizeRefundStatus(?string $status): string
    {
        return match (self::normalize($status)) {
            'approved' => self::REFUND_APPROVED,
            'rejected' => self::REFUND_REJECTED,
            'partial', 'partially paid', 'partially_paid' => self::REFUND_PARTIALLY_PAID,
            'paid', 'full' => self::REFUND_PAID,
            'void', 'voided' => self::REFUND_VOIDED,
            default => self::REFUND_PENDING,
        };
    }

    public static function normalize(?string $status): string
    {
        $value = strtolower(trim((string) $status));
        $value = str_replace('_', ' ', $value);
        $value = preg_replace('/\s+/', ' ', $value) ?? $value;

        return $value;
    }
}
