<?php

namespace App\Domains\Event\Controllers;

use App\Domains\Event\Actions\SetEventAddons\SetEventAddonsCommand;
use App\Domains\Event\Actions\SetEventAddons\SetEventAddonsRequest;
use App\Domains\Event\Actions\SetParticipationFees\SetParticipationFeesCommand;
use App\Domains\Event\Actions\SetParticipationFees\SetParticipationFeesRequest;
use App\Domains\Event\Actions\SetParticipationOptions\SetParticipationOptionsCommand;
use App\Domains\Event\Actions\SetParticipationOptions\SetParticipationOptionsRequest;
use App\Domains\Event\Actions\SetPaymentMethods\SetPaymentMethodsCommand;
use App\Domains\Event\Actions\SetPaymentMethods\SetPaymentMethodsRequest;
use App\Domains\Event\Actions\UpdateEvent\UpdateEventCommand;
use App\Domains\Event\Actions\UpdateEvent\UpdateEventRequest;
use App\Domains\Event\Actions\UpdateManagers\UpdateManagersCommand;
use App\Domains\Event\Actions\UpdateManagers\UpdateManagersRequest;
use App\Enumerations\ParticipationFeeType;
use App\Enumerations\ParticipationType;
use App\Providers\InertiaProvider;
use App\Providers\PdfGenerateAndDownloadProvider;
use App\Scopes\CommonController;
use App\ValueObjects\Amount;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class DetailsController extends CommonController {
    public function __invoke(string $eventId) {
        $event = $this->events->getByIdentifier($eventId);
        return new InertiaProvider('Event/Details', ['event' => $event])->render();
    }

    public function summary(int $eventId, Request $request) : JsonResponse {
        $event = $this->events->getById($eventId);
        return response()->json(['event' => $event->toResource()->toArray($request)]);
    }

    public function updateCommonSettings(int $eventId, Request $request) : JsonResponse {
        $event = $this->events->getById($eventId);

        $earlyBirdEnd = \DateTime::createFromFormat('Y-m-d', $request->input('earlyBirdEnd'));
        $registrationFinalEnd = \DateTime::createFromFormat('Y-m-d', $request->input('registrationFinalEnd'));
        $flatSupport = Amount::fromString($request->input('flatSupport'));
        $supportPerPerson = Amount::fromString($request->input('supportPerson'));

        $contributinLocalGroups = $request->input('contributingLocalGroups');
        $eatingHabits = $request->input('eatingHabits');

        $eventUpdateRequest = new UpdateEventRequest(
            $event,
            $request->input('eventName'),
            $request->input('eventLocation'),
            $request->input('postalCode'),
            $request->input('email'),
            $earlyBirdEnd,
            $registrationFinalEnd,
            $request->input('alcoholicsAge'),
            $request->input('sendWeeklyReports'),
            $request->input('registrationAllowed'),
            $flatSupport,
            $supportPerPerson,
            $contributinLocalGroups,
            $eatingHabits
        );

        $eventUpdateCommand = new UpdateEventCommand($eventUpdateRequest);
        $response = $eventUpdateCommand->execute();

        return response()->json(['status' => $response->success ? 'success' : 'error', 'message' => $response->message]);
    }

    public function updatePaymentMethods(int $eventId, Request $request): JsonResponse
    {
        $event = $this->events->getById($eventId);

        $paymentMethods = $request->input('paymentMethods', []);
        $paymentMethodConfigurations = (array)$request->input('paymentMethodConfigurations', []);

        $setPaymentMethodsRequest = new SetPaymentMethodsRequest($event, $paymentMethods, $paymentMethodConfigurations);
        $setPaymentMethodsCommand = new SetPaymentMethodsCommand($setPaymentMethodsRequest);
        $response = $setPaymentMethodsCommand->execute();

        return response()->json(['status' => $response->success ? 'success' : 'error', 'message' => $response->message]);
    }

    public function updateEventManagers(int $eventId, Request $request) : JsonResponse {
        $event = $this->events->getById($eventId);

        $updateEventManagersRequest = new UpdateManagersRequest($event, $request->input('selectedManagers'));
        $updateEventManagersCommand = new UpdateManagersCommand($updateEventManagersRequest);
        $response = $updateEventManagersCommand->execute();
        return response()->json(['status' => $response->success ? 'success' : 'error']);
    }

    public function updateParticipationFees(int $eventId, Request $request) : JsonResponse {
        $event = $this->events->getById($eventId);

        $participationFeeFirst = [
            'type' => ParticipationType::PARTICIPATION_TYPE_PARTICIPANT,
            'name' => 'Teilnehmer',
            'description' => $request->input('pft_1_description'),
            'amount_standard' => Amount::fromString($request->input('pft_1_amount_standard')),
            'amount_reduced' => null !== $request->input('pft_1_amount_reduced') ? Amount::fromString($request->input('pft_1_amount_reduced')) : null,
            'amount_solidarity' => null !== $request->input('pft_1_amount_solidarity') ? Amount::fromString($request->input('pft_1_amount_solidarity')) : null
        ];

        $siblingReduction = $request->input('sibling_reduction') ?? false;
        $participationFeeRequest = new SetParticipationFeesRequest($event, $participationFeeFirst, $siblingReduction);

        if ($request->input('pft_2_active')) {
            $participationFeeRequest->participationFeeSecond = [
                'type' => ParticipationType::PARTICIPATION_TYPE_TEAM,
                'name' => $event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED ? 'Kernteam' : 'Solidaritätsbeitrag',
                'description' => $request->input('pft_2_description'),
                'amount_standard' => Amount::fromString($request->input('pft_2_amount_standard')),
                'amount_reduced' => null !== $request->input('pft_2_amount_reduced') ? Amount::fromString($request->input('pft_2_amount_reduced')) : null,
                'amount_solidarity' => null !== $request->input('pft_2_amount_solidarity') ? Amount::fromString($request->input('pft_2_amount_solidarity')) : null
            ];
        }

        if ($request->input('pft_3_active')) {
            $participationFeeRequest->participationFeeThird = [
                'type' => ParticipationType::PARTICIPATION_TYPE_VOLUNTEER,
                'name' => $event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED ? 'Unterstützende' : 'Reduzierter Beitrag',
                'description' => $event->participation_fee_type !== ParticipationFeeType::PARTICIPATION_FEE_TYPE_SOLIDARITY ? $request->input('pft_3_description') : 'Nach Verfügbarkeit',
                'amount_standard' => Amount::fromString($request->input('pft_3_amount_standard')),
                'amount_reduced' => null !== $request->input('pft_3_amount_reduced') ? Amount::fromString($request->input('pft_3_amount_reduced')) : null,
                'amount_solidarity' => null !== $request->input('pft_3_amount_solidarity') ? Amount::fromString($request->input('pft_3_amount_solidarity')) : null
            ];
        }

        if ($request->input('pft_4_active') && $event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED) {
            $participationFeeRequest->participationFeeFourth = [
                'type' => ParticipationType::PARTICIPATION_TYPE_OTHER,
                'name' => 'Sonstige',
                'description' => $request->input('pft_4_description'),
                'amount_standard' => Amount::fromString($request->input('pft_4_amount_standard')),
                'amount_reduced' => null !== $request->input('pft_4_amount_reduced') ? Amount::fromString($request->input('pft_4_amount_reduced')) : null,
                'amount_solidarity' => null !== $request->input('pft_4_amount_solidarity') ? Amount::fromString($request->input('pft_4_amount_solidarity')) : null
            ];
        }

        $participationFeeCommand = new SetParticipationFeesCommand($participationFeeRequest);
        $response = $participationFeeCommand->execute();

        return response()->json(['status' => $response->success ? 'success' : 'error']);
    }

    public function updateParticipationOptions(int $eventId, Request $request): JsonResponse
    {
        $event = $this->events->getById($eventId);

        $setRequest = new SetParticipationOptionsRequest($event, (array)$request->input('questions', []));
        $setCommand = new SetParticipationOptionsCommand($setRequest);
        $response = $setCommand->execute();

        return response()->json(['status' => $response->success ? 'success' : 'error', 'message' => $response->message]);
    }

    public function updateEventAddons(int $eventId, Request $request): JsonResponse
    {
        $event = $this->events->getById($eventId);

        $setRequest = new SetEventAddonsRequest($event, (array)$request->input('addons', []));
        $setCommand = new SetEventAddonsCommand($setRequest);
        $response = $setCommand->execute();

        return response()->json(['status' => $response->success ? 'success' : 'error', 'message' => $response->message]);
    }

    public function downloadPdfList(string $eventId, string $listType, Request $request): Response
    {
        $event = $this->events->getByIdentifier($eventId);

        $participants = $this->eventParticipants->getForList($event, $request);
        $kitchenOverview = $this->eventParticipants->getKitchenOverview($event);
        $html = view('pdfs.' . $listType, [
            'event' => $event->name,
            'eventStart' => $event->start_date,
            'eventEnd' => $event->end_date,
            'rows' => $participants,
            'kitchenRequirements' => $kitchenOverview,
            'participantsForKitchenList' => $this->eventParticipants->getParticipantsWithIntolerances($event, $request),
        ])->render();

        $pdf = PdfGenerateAndDownloadProvider::fromHtml(
            $html,
            'landscape'
        );

        return response($pdf, 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="' . $listType .'.pdf"',
        ]);
    }

    public function downloadCsvList(string $eventId, string $listType, Request $request): Response
    {
        $event = $this->events->getByIdentifier($eventId);

        $participants = $this->eventParticipants->getForList($event, $request);
        $kitchenOverview = $this->eventParticipants->getKitchenOverview($event);

        $csv = view('csvs.' . $listType, [
            'event' => $event->name,
            'rows' => $participants,
        ])->render();

        return response($csv, 200, [
            'Content-Type' => 'text/csv; charset=UTF-8',
            'Content-Disposition' => 'attachment; filename="' . $listType . '.csv"',
        ]);
    }

    public function listParticipants(string $eventId, string $listType, Request $request) : JsonResponse {
        $event = $this->events->getByIdentifier($eventId);
        switch ($listType) {
            case 'by-local-group':
                $participants = $this->eventParticipants->groupByLocalGroup($event, $request);
                break;
            case 'by-participation-group':
                $participants = $this->eventParticipants->groupByParticipationType($event, $request);
                break;
            case 'by-participation-option':
                $participants = $this->eventParticipants->groupByParticipationOption($event, $request);
                break;
            case 'by-addon':
                $participants = $this->eventParticipants->groupByAddon($event, $request);
                break;
            case 'signed-off':
                $participants = $this->eventParticipants->getSignedOffParticipants($event, $request);
                break;
            default:
                $participants = ['Alle Teilnehmenden' => $this->eventParticipants->getForList($event, $request)];
        }

        return response()->json([
            'participants' => $participants,
            'listType' => $listType,
            'event' => $event->toResource()->toArray($request)
        ]);
    }
}
