<?php

namespace App\Mail\ParticipantParticipationMails;

use App\Domains\Event\Actions\GenerateIcal\GenerateIcalCommand;
use App\Domains\Event\Actions\GenerateIcal\GenerateIcalRequest;
use App\Domains\Event\Actions\GenerateIcal\GenerateIcalResponse;
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineCommand;
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineRequest;
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineResponse;
use App\EventPaymentModules\DTO\RegistrationRenderContext;
use App\EventPaymentModules\ProvidesGiroCode;
use App\Models\EventParticipant;
use Illuminate\Bus\Queueable;
use Illuminate\Http\Request;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class EventSignUpSuccessfullMail extends Mailable
{
    use Queueable, SerializesModels;

    private ?GenerateIcalResponse $participationIcal = null;
    private ?GenerateIcalForDeadlineResponse $deadlineIcal = null;


    /**
     * Create a new message instance.
     */
    public function __construct(
        private EventParticipant $participant,
    )
    {
        //
    }

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        $participant = $this->participant->toResource()->toArray(new Request());

        $subject = sprintf(
            $participant['needs_payment'] ? 'Teilnahme- & Zahlungsinformationen %1$s %2$s' : 'Anmeldebestätigung %1$s %2$s',
            'für die Veranstaltung',
            $this->participant->event()->first()->name
        );


        return new Envelope(
            subject: $subject,
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        $event = $this->participant->event()->first()->toResource()->toArray(new Request());
        $participant = $this->participant->toResource()->toArray(new Request());

        $module = $this->participant->paymentModule();
        $girocodeBinary = $module instanceof ProvidesGiroCode
            ? $module->giroCode($this->participant, $this->participant->paymentConfiguration())
            : null;

        // Zahlungs-Block im Mail-Kontext erzeugen (GiroCode als cid: statt Web-Endpoint).
        $paymentSummary = $this->participant->paymentSummary(RegistrationRenderContext::Mail);

        $participationIcal = $this->getParticipationIcal();
        $deadlineIcal = $this->getDeadlineIcal();


        return new Content(
            view: 'emails.events.signup_complete',
            with: [
                'participationType' => $participant['participationType'],
                'name' => $participant['nicename'],
                'eventTitle' => $event['name'],
                'eventEmail' => $event['email'],
                'arrival' => $participant['arrival'],
                'departure' => $participant['departure'],
                'amount' => $participant['amount_left_string'],
                'paymentFinalDate' => $event['registrationFinalEnd']['formatted'],
                'paymentSummary' => ['hasPaymentInformation' => $paymentSummary->hasPaymentInformation, 'html' => $paymentSummary->html],
                'girocodeBinary' => $girocodeBinary,
                'efzStatus' => $participant['efz_status'],
                'participationIcalFilename' => $participationIcal->filename,
                'deadlineIcalFilename' => $deadlineIcal->filename,
            ],
        );
    }


    public function attachments(): array
    {
        $attachments = [
            Attachment::fromData(
                fn () => $this->getParticipationIcal()->icalContent,
                $this->getParticipationIcal()->filename
            )->withMime('text/calendar'),
        ];

        $participant = $this->participant->toResource()->toArray(new Request());


        if ($participant['needs_payment']) {
            /*$attachments[] = [
                Attachment::fromData(
                    fn () => $this->getDeadlineIcal()->icalContent,
                    $this->getDeadlineIcal()->filename
                )->withMime('text/calendar'),
            ];*/
        }

        return $attachments;
    }

    private function getDeadlineIcal(): GenerateIcalForDeadlineResponse
    {
        if ($this->deadlineIcal === null) {
            $this->deadlineIcal = (new GenerateIcalForDeadlineCommand(
                new GenerateIcalForDeadlineRequest($this->participant->event()->first())
            ))->execute();
        }

        return $this->deadlineIcal;
    }

    private function getParticipationIcal(): GenerateIcalResponse
    {
        if ($this->participationIcal === null) {
            $this->participationIcal = (new GenerateIcalCommand(
                new GenerateIcalRequest($this->participant)
            ))->execute();
        }

        return $this->participationIcal;
    }
}
