<?php

namespace Database\Seeders;

use App\Enums\PaymentProofReviewStatus;
use App\Enums\PaymentStatus;
use App\Enums\RegistrationStatus;
use App\Models\Event;
use App\Models\EventPaymentProof;
use App\Models\EventRegistration;
use App\Models\EventRegistrationStatusEvent;
use App\Models\ManualPaymentMethod;
use App\Models\PlayerGameProfile;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Storage;

class EventRegistrationSeeder extends Seeder
{
    public function run(): void
    {
        $freeEvent = Event::query()->where('slug', 'alga-open-scrim-cup')->first();
        $paidEvent = Event::query()->where('slug', 'alga-premier-league')->first();
        $waitlistEvent = Event::query()->where('slug', 'alga-quick-cup')->first();
        $reviewEvent = Event::query()->where('slug', 'alga-community-qualifier')->first();
        $admin = User::query()->where('email', 'admin@algaarena.gg')->first();
        $instapay = ManualPaymentMethod::query()->where('type', 'instapay')->first();

        if ($freeEvent) {
            $this->seedFreeRegistration(
                $freeEvent,
                'nightfalcon@algaarena.gg',
                RegistrationStatus::Confirmed,
                PaymentStatus::NotRequired,
                confirmed: true,
            );

            $this->seedFreeRegistration(
                $freeEvent,
                'stellarx@algaarena.gg',
                RegistrationStatus::Confirmed,
                PaymentStatus::NotRequired,
                confirmed: true,
            );
        }

        if ($waitlistEvent) {
            $this->seedFreeRegistration(
                $waitlistEvent,
                'nightfalcon@algaarena.gg',
                RegistrationStatus::Confirmed,
                PaymentStatus::NotRequired,
                confirmed: true,
            );

            $this->seedFreeRegistration(
                $waitlistEvent,
                'stellarx@algaarena.gg',
                RegistrationStatus::Confirmed,
                PaymentStatus::NotRequired,
                confirmed: true,
            );

            $this->seedFreeRegistration(
                $waitlistEvent,
                'sandstorm@algaarena.gg',
                RegistrationStatus::Waitlisted,
                PaymentStatus::NotRequired,
                waitlistPosition: 1,
            );
        }

        if ($reviewEvent) {
            $this->seedFreeRegistration(
                $reviewEvent,
                'sandstorm@algaarena.gg',
                RegistrationStatus::Pending,
                PaymentStatus::NotRequired,
            );
        }

        if ($paidEvent && $instapay) {
            $this->seedPaidRegistration(
                $paidEvent,
                'sandstorm@algaarena.gg',
                RegistrationStatus::PendingPayment,
                PaymentStatus::Pending,
            );

            $review = $this->seedPaidRegistration(
                $paidEvent,
                'stellarx@algaarena.gg',
                RegistrationStatus::PaymentReview,
                PaymentStatus::ProofSubmitted,
            );

            if ($review) {
                $this->seedPaymentProof($review, $instapay, PaymentProofReviewStatus::Pending);
            }

            $confirmed = $this->seedPaidRegistration(
                $paidEvent,
                'nightfalcon@algaarena.gg',
                RegistrationStatus::Confirmed,
                PaymentStatus::Confirmed,
                confirmed: true,
                reviewedBy: $admin?->id,
            );

            if ($confirmed) {
                $proof = $this->seedPaymentProof($confirmed, $instapay, PaymentProofReviewStatus::Approved, $admin?->id);
                if ($proof) {
                    $proof->update([
                        'reviewed_at' => now()->subDay(),
                        'transfer_reference' => 'INST-20260719-001',
                        'amount_minor' => 25000,
                    ]);
                }
            }
        }
    }

    private function seedFreeRegistration(
        Event $event,
        string $email,
        RegistrationStatus $status,
        PaymentStatus $paymentStatus,
        bool $confirmed = false,
        ?int $waitlistPosition = null,
    ): ?EventRegistration {
        return $this->seedRegistration($event, $email, $status, $paymentStatus, $confirmed, $waitlistPosition);
    }

    private function seedPaidRegistration(
        Event $event,
        string $email,
        RegistrationStatus $status,
        PaymentStatus $paymentStatus,
        bool $confirmed = false,
        ?int $reviewedBy = null,
    ): ?EventRegistration {
        return $this->seedRegistration($event, $email, $status, $paymentStatus, $confirmed, null, $reviewedBy);
    }

    private function seedRegistration(
        Event $event,
        string $email,
        RegistrationStatus $status,
        PaymentStatus $paymentStatus,
        bool $confirmed = false,
        ?int $waitlistPosition = null,
        ?int $reviewedBy = null,
    ): ?EventRegistration {
        $user = User::query()->where('email', $email)->with('playerProfile')->first();
        if (! $user?->playerProfile) {
            return null;
        }

        $gameProfile = PlayerGameProfile::query()
            ->where('player_profile_id', $user->playerProfile->id)
            ->where('game_id', $event->game_id)
            ->first();

        if (! $gameProfile) {
            return null;
        }

        $registration = EventRegistration::updateOrCreate(
            [
                'event_id' => $event->id,
                'user_id' => $user->id,
            ],
            [
                'player_profile_id' => $user->playerProfile->id,
                'player_game_profile_id' => $gameProfile->id,
                'status' => $status,
                'payment_status' => $paymentStatus,
                'contact_name' => $user->display_name,
                'contact_email' => $user->email,
                'contact_phone_e164' => $user->phone_e164 ?? '+201000000000',
                'contact_whatsapp' => true,
                'registered_at' => now()->subDays(3),
                'confirmed_at' => $confirmed ? now()->subDays(2) : null,
                'reviewed_by' => $reviewedBy,
                'reviewed_at' => $reviewedBy ? now()->subDay() : null,
                'waitlist_position' => $waitlistPosition,
            ],
        );

        EventRegistrationStatusEvent::updateOrCreate(
            [
                'event_registration_id' => $registration->id,
                'new_status' => $status->value,
            ],
            [
                'old_status' => null,
                'changed_by' => $user->id,
                'reason' => 'Seeded demo registration',
                'created_at' => now()->subDays(3),
            ],
        );

        return $registration;
    }

    private function seedPaymentProof(
        EventRegistration $registration,
        ManualPaymentMethod $method,
        PaymentProofReviewStatus $reviewStatus,
        ?int $reviewedBy = null,
    ): ?EventPaymentProof {
        $path = 'demo/'.$registration->public_id.'.png';
        $this->ensureDemoProofFile($path);

        return EventPaymentProof::updateOrCreate(
            [
                'event_registration_id' => $registration->id,
                'manual_payment_method_id' => $method->id,
            ],
            [
                'file_path' => $path,
                'original_name' => 'payment-receipt.png',
                'mime_type' => 'image/png',
                'size' => Storage::disk('payment_proofs')->size($path),
                'transfer_reference' => 'INST-DEMO-'.substr($registration->public_id, 0, 8),
                'amount_minor' => 25000,
                'user_notes' => 'Demo payment proof for development.',
                'review_status' => $reviewStatus,
                'reviewed_by' => $reviewedBy,
                'reviewed_at' => $reviewedBy ? now()->subDay() : null,
            ],
        );
    }

    private function ensureDemoProofFile(string $path): void
    {
        $disk = Storage::disk('payment_proofs');

        if ($disk->exists($path)) {
            return;
        }

        $disk->makeDirectory('demo');

        // 1x1 transparent PNG
        $png = base64_decode(
            'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
            true,
        );

        $disk->put($path, $png);
    }
}
