<?php

namespace App\Models;

use App\Casts\AmountCast;
use App\Enumerations\EatingHabit;
use App\Enumerations\EfzStatus;
use App\Enumerations\FirstAidPermission;
use App\Enumerations\ParticipationType;
use App\Enumerations\SwimmingPermission;
use App\EventPaymentModules\DTO\RegistrationRenderContext;
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
use App\EventPaymentModules\EventPaymentModule;
use App\EventPaymentModules\EventPaymentModuleRegistry;
use App\Scopes\InstancedModel;
use Illuminate\Database\Eloquent\Relations\HasMany;


class EventParticipant extends InstancedModel
{
    protected $table = 'event_participants';

    protected $fillable = [
        'tenant',
        'event_id',
        'user_id',
        'identifier',

        'firstname',
        'lastname',
        'nickname',

        'participation_type',
        'local_group',
        'birthday',

        'address_1',
        'address_2',
        'postcode',
        'city',

        'email_1',
        'phone_1',
        'email_2',
        'phone_2',
        'contact_person',

        'allergies',
        'intolerances',
        'medications',
        'tetanus_vaccination',
        'eating_habit',
        'swimming_permission',
        'first_aid_permission',

        'foto_socialmedia',
        'foto_print',
        'foto_webseite',
        'foto_partner',
        'foto_intern',

        'arrival_date',
        'departure_date',
        'arrival_eating',
        'departure_eating',

        'notes',
        'amount',
        'amount_paid',
        'payment_purpose',
        'payment_method',
        'payment_options',
        'efz_status',
        'unregistered_at',
    ];

    protected $casts = [
        'birthday' => 'date',
        'tetanus_vaccination' => 'date',
        'arrival_date' => 'date',
        'departure_date' => 'date',
        'unregistered_at' => 'date',

        'foto_socialmedia' => 'boolean',
        'foto_print' => 'boolean',
        'foto_webseite' => 'boolean',
        'foto_partner' => 'boolean',
        'foto_intern' => 'boolean',

        'amount' => AmountCast::class,
        'amount_paid' => AmountCast::class,
        'payment_options' => 'array',
    ];

    /*
    |--------------------------------------------------------------------------
    | Relationships
    |--------------------------------------------------------------------------
    */

    public function event()
    {
        return $this->belongsTo(Event::class);
    }

    /** Gewählte Teilnahmeoptionen (event-spezifische Pflicht-Auswahl) dieser Anmeldung. */
    public function selectedOptions(): HasMany
    {
        return $this->hasMany(EventParticipantOption::class, 'event_participant_id');
    }

    /** Gebuchte Zusätze (Event-Addons) dieser Anmeldung. */
    public function selectedAddons(): HasMany
    {
        return $this->hasMany(EventParticipantAddon::class, 'event_participant_id');
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function tenantRelation()
    {
        return $this->belongsTo(Tenant::class, 'tenant', 'slug');
    }

    public function localGroup()
    {
        return $this->belongsTo(Tenant::class, 'local_group', 'slug');
    }

    public function participationType()
    {
        return $this->belongsTo(ParticipationType::class, 'participation_type', 'slug');
    }

    public function swimmingPermission()
    {
        return $this->belongsTo(SwimmingPermission::class, 'swimming_permission', 'slug');
    }

    public function eatingHabit()
    {
        return $this->belongsTo(EatingHabit::class, 'eating_habits', 'slug');
    }

    public function paymentMethod()
    {
        return $this->belongsTo(\App\Models\PaymentMethod::class, 'payment_method', 'slug');
    }

    public function firstAidPermission()
    {
        return $this->belongsTo(FirstAidPermission::class, 'first_aid_permission', 'slug');
    }

    public function efzStatus()
    {
        return $this->belongsTo(EfzStatus::class, 'efz_status', 'slug');
    }

    public function getOfficialName() : string {
        return sprintf('%1$s %2$s', $this->firstname, $this->lastname);
    }

    public function getFullName() : string {
        if ($this->nickname === null || trim($this->nickname) === '') {
            return sprintf('%1$s %2$s', $this->firstname, $this->lastname)
                |>trim(...);
        }


        return sprintf('%1$1s%2$s(%3$s %4$s)',
                $this->nickname,
                '<br />',
                $this->firstname,
                $this->lastname,
            )
                |>trim(...);
    }

    public function getNicename() : string {
        return $this->nickname ?? $this->firstname;
    }

    /*
    |--------------------------------------------------------------------------
    | Zahlungsmodul
    |--------------------------------------------------------------------------
    */

    /** Das Zahlungsmodul der gewählten Zahlungsart des Teilnehmers. */
    public function paymentModule(): ?EventPaymentModule
    {
        return $this->payment_method !== null
            ? EventPaymentModuleRegistry::forSlug($this->payment_method)
            : null;
    }

    /**
     * Aufgelöste pro-Event-Konfiguration der gewählten Zahlungsart (event_payment_methods.configuration).
     *
     * Nutzt die Relation-Property, damit sie via `->with('event.paymentMethods')` eager geladen und in
     * Teilnehmerlisten (gleiches Event teilt dieselbe Event-Instanz) ohne N+1 aufgelöst werden kann.
     *
     * @return array<string, mixed>
     */
    public function paymentConfiguration(): array
    {
        if ($this->payment_method === null) {
            return [];
        }

        $method = $this->event?->paymentMethods->firstWhere('slug', $this->payment_method);

        return $method?->pivot->configuration ?? [];
    }

    /** Zahlungs-Zusammenfassung (Anmeldeabschluss/Mail), vom Zahlungsmodul als fertiges HTML erzeugt. */
    public function paymentSummary(RegistrationRenderContext $context = RegistrationRenderContext::Web): RegistrationSummaryResponse
    {
        $module = $this->paymentModule();
        if ($module === null) {
            return new RegistrationSummaryResponse();
        }

        return $module->registrationSummary(new RegistrationSummaryRequest($this, $this->paymentConfiguration(), $context));
    }
}
