<?php

namespace App\Actions\Payments;

use App\Enums\PaymentProofReviewStatus;
use App\Enums\PaymentStatus;
use App\Enums\RegistrationStatus;
use App\Events\PaymentProofReviewed;
use App\Models\EventPaymentProof;
use App\Models\EventRegistration;
use App\Models\ManualPaymentMethod;
use App\Models\User;
use App\Services\AuditLogger;
use App\Services\MediaUploadService;
use App\Services\RegistrationStatusService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;

class SubmitPaymentProofAction
{
    public function __construct(
        private MediaUploadService $mediaUpload,
        private RegistrationStatusService $registrationStatus,
    ) {}

    public function execute(EventRegistration $registration, User $user, array $data, UploadedFile $proof): EventPaymentProof
    {
        return DB::transaction(function () use ($registration, $user, $data, $proof) {
            if ($registration->user_id !== $user->id) {
                throw new InvalidArgumentException(__('events.errors.unauthorized'));
            }

            if (! in_array($registration->status, [RegistrationStatus::PendingPayment, RegistrationStatus::PaymentReview], true)) {
                throw new InvalidArgumentException(__('events.errors.invalid_status'));
            }

            $method = ManualPaymentMethod::query()
                ->whereKey($data['manual_payment_method_id'])
                ->where('is_active', true)
                ->firstOrFail();

            $upload = $this->mediaUpload->uploadPrivateFile(
                $proof,
                'registrations/'.$registration->public_id,
                ['mimes' => ['jpg', 'jpeg', 'png', 'webp', 'pdf'], 'max_kb' => 10240],
            );

            $paymentProof = EventPaymentProof::query()->create([
                'event_registration_id' => $registration->id,
                'manual_payment_method_id' => $method->id,
                'file_path' => $upload['path'],
                'original_name' => $upload['original_name'],
                'mime_type' => $upload['mime_type'],
                'size' => $upload['size'],
                'transfer_reference' => $data['transfer_reference'] ?? null,
                'amount_minor' => $data['amount_minor'] ?? $registration->event->fee_amount_minor,
                'user_notes' => $data['user_notes'] ?? null,
                'review_status' => PaymentProofReviewStatus::Pending,
            ]);

            $oldStatus = $registration->status;

            $this->registrationStatus->record(
                $registration,
                RegistrationStatus::PaymentReview,
                $oldStatus,
                $user,
                'Payment proof submitted',
            );

            $registration->update(['payment_status' => PaymentStatus::ProofSubmitted]);

            event(new PaymentProofReviewed(
                proof: $paymentProof->load(['eventRegistration.event', 'eventRegistration.user']),
                action: PaymentProofReviewed::ACTION_SUBMITTED,
            ));

            return $paymentProof->load('manualPaymentMethod');
        });
    }
}
