<?php

namespace App\Jobs;

use App\Enums\FormType;
use App\Mail\ApplicationPdfMail;
use App\Models\AdoptionApplication;
use App\Models\ApplicationAnswer;
use App\Models\AssistanceApplication;
use App\Models\FormQuestionGroup;
use App\Models\FosteringApplication;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Mail;

class SendApplicationPdfEmail implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public AdoptionApplication|FosteringApplication|AssistanceApplication $application,
        public string $recipientEmail
    ) {}

    public function handle(): void
    {
        $application = $this->loadApplicationWithRelations();
        $applicationType = $this->getApplicationType();
        $pdfContent = $this->generatePdf($application, $applicationType);

        Mail::to($this->recipientEmail)->send(
            new ApplicationPdfMail($application, $pdfContent, $applicationType)
        );
    }

    protected function loadApplicationWithRelations(): AdoptionApplication|FosteringApplication|AssistanceApplication
    {
        $relations = ['user', 'answers'];

        if ($this->application instanceof AdoptionApplication) {
            $relations = array_merge($relations, ['pet.species', 'pet.breed', 'secondPet.species', 'secondPet.breed']);
        }

        return $this->application->load($relations);
    }

    protected function getApplicationType(): string
    {
        return FormType::fromApplication($this->application)->value;
    }

    protected function generatePdf(AdoptionApplication|FosteringApplication|AssistanceApplication $application, string $type): string
    {
        $groupedAnswers = $this->getGroupedAnswers($application);

        $pdf = Pdf::loadView('pdf.application', [
            'application' => $application,
            'applicant' => $application->user,
            'groupedAnswers' => $groupedAnswers,
            'applicationType' => $type,
            'pet' => $application instanceof AdoptionApplication ? $application->pet : null,
            'secondPet' => $application instanceof AdoptionApplication ? $application->secondPet : null,
        ]);

        return $pdf->output();
    }

    /**
     * @return Collection<array-key, array{group_id: int|string, group_name: string, answers: \Illuminate\Database\Eloquent\Collection<int, ApplicationAnswer>}>
     */
    protected function getGroupedAnswers(AdoptionApplication|FosteringApplication|AssistanceApplication $application): Collection
    {
        /** @var \Illuminate\Database\Eloquent\Collection<int, ApplicationAnswer> $answers */
        $answers = $application->answers;

        return $answers->groupBy(function ($answer): int|string {
            return $answer->question_snapshot['group_id'] ?? 'ungrouped';
        })->sortKeys()->map(function ($groupAnswers, $groupId) {
            /** @var \Illuminate\Database\Eloquent\Collection<int, ApplicationAnswer> $groupAnswers */
            /** @var int|string $groupId */
            $firstSnapshot = $groupAnswers->first()->question_snapshot;

            return [
                'group_id' => $groupId,
                'group_name' => $this->getGroupName($groupId, $firstSnapshot) ?? '',
                'answers' => $groupAnswers,
            ];
        });
    }

    /**
     * @param  array<string, mixed>  $snapshot
     */
    protected function getGroupName(string|int $groupId, array $snapshot): ?string
    {
        if ($groupId === 'ungrouped') {
            return 'General Questions';
        }

        return $snapshot['group_name'] ?? FormQuestionGroup::find($groupId)?->name;
    }
}
