<?php

namespace App\Services;

use App\Enums\PaymentTransactionStatus;
use App\Enums\PaymentTransactionType;
use App\Models\CreditLedgerEntry;
use App\Models\CreditProduct;
use App\Models\PaymentTransaction;
use App\Models\User;

class PaymentTransactionRecorder
{
    /**
     * @param  array<string, mixed>|null  $payload
     */
    public function recordCheckoutSession(
        ?User $user,
        ?CreditProduct $product,
        string $stripeCheckoutSessionId,
        PaymentTransactionStatus $status = PaymentTransactionStatus::PENDING,
        ?string $stripeEventId = null,
        ?string $stripeEventType = null,
        ?string $stripeCustomerId = null,
        ?string $stripePaymentIntentId = null,
        ?int $amount = null,
        ?string $currency = null,
        ?int $creditsExpected = null,
        ?int $creditsGranted = null,
        ?CreditLedgerEntry $ledgerEntry = null,
        ?string $invoiceUrl = null,
        ?string $invoicePdfUrl = null,
        ?string $errorMessage = null,
        ?array $payload = null,
    ): PaymentTransaction {
        return PaymentTransaction::query()->updateOrCreate([
            'stripe_checkout_session_id' => $stripeCheckoutSessionId,
        ], [
            'user_id' => $user?->getKey(),
            'credit_product_id' => $product?->getKey(),
            'credit_ledger_entry_id' => $ledgerEntry?->getKey(),
            'type' => PaymentTransactionType::CHECKOUT,
            'status' => $status,
            'stripe_event_id' => $stripeEventId,
            'stripe_event_type' => $stripeEventType,
            'stripe_customer_id' => $stripeCustomerId,
            'stripe_payment_intent_id' => $stripePaymentIntentId,
            'amount' => $amount,
            'currency' => $currency,
            'credits_expected' => $creditsExpected ?? $product?->credits,
            'credits_granted' => $creditsGranted ?? 0,
            'invoice_url' => $invoiceUrl,
            'invoice_pdf_url' => $invoicePdfUrl,
            'error_message' => $errorMessage,
            'payload' => $payload,
            'processed_at' => $status === PaymentTransactionStatus::PENDING ? null : now(),
        ]);
    }

    /**
     * @param  array<string, mixed>|null  $payload
     */
    public function recordInvoice(
        ?User $user,
        ?CreditProduct $product,
        string $stripeInvoiceId,
        ?string $stripePriceId,
        PaymentTransactionStatus $status,
        ?string $stripeEventId = null,
        ?string $stripeEventType = null,
        ?string $stripeCustomerId = null,
        ?string $stripePaymentIntentId = null,
        ?string $stripeSubscriptionId = null,
        ?int $amount = null,
        ?string $currency = null,
        ?int $creditsExpected = null,
        ?int $creditsGranted = null,
        ?CreditLedgerEntry $ledgerEntry = null,
        ?string $invoiceUrl = null,
        ?string $invoicePdfUrl = null,
        ?string $errorMessage = null,
        ?array $payload = null,
    ): PaymentTransaction {
        return PaymentTransaction::query()->updateOrCreate([
            'stripe_invoice_id' => $stripeInvoiceId,
            'stripe_price_id' => $stripePriceId,
        ], [
            'user_id' => $user?->getKey(),
            'credit_product_id' => $product?->getKey(),
            'credit_ledger_entry_id' => $ledgerEntry?->getKey(),
            'type' => PaymentTransactionType::SUBSCRIPTION_INVOICE,
            'status' => $status,
            'stripe_event_id' => $stripeEventId,
            'stripe_event_type' => $stripeEventType,
            'stripe_customer_id' => $stripeCustomerId,
            'stripe_payment_intent_id' => $stripePaymentIntentId,
            'stripe_subscription_id' => $stripeSubscriptionId,
            'amount' => $amount,
            'currency' => $currency,
            'credits_expected' => $creditsExpected ?? $product?->credits,
            'credits_granted' => $creditsGranted ?? 0,
            'invoice_url' => $invoiceUrl,
            'invoice_pdf_url' => $invoicePdfUrl,
            'error_message' => $errorMessage,
            'payload' => $payload,
            'processed_at' => now(),
        ]);
    }
}
