<?php

namespace App\Service;

use App\DataObjects\TicketData;
use App\DataObjects\TicketFormData;
use App\Entity\Customer;
use App\Entity\Payment;
use App\Entity\Ticket;
use App\Enum\TicketData as TicketEnum;
use App\Repository\PaymentRepository;
use Doctrine\ORM\EntityManagerInterface;
use Stripe\Checkout\Session;
use Stripe\Stripe;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class TicketService
{
    public function __construct(
        private readonly UrlGeneratorInterface $generator,
        private readonly EntityManagerInterface $em,
        private readonly PaymentRepository $paymentRepository,
        private readonly TicketEmailService $emailService,
        #[Autowire(env: 'STRIPE_SECRET_KEY')]
        string $stripeKey
    ) {
        Stripe::setApiKey($stripeKey);
    }

    public function handleTicketData(TicketFormData $data): Session
    {
        $session = $this->createSession($this->getLineItems($data->tickets, $data->personal->donation), $data->personal->email);

        $this->saveTicketData($data, $session->id);

        return $session;
    }

    public function completePayment(string $sessionId): bool
    {
        if (!$payment = $this->paymentRepository->findOneBy(['sessionId' => $sessionId])) {
            return false;
        }

        $payment->setCompleted(true);
        $this->em->flush();

        $this->emailService->sendSuccessEmail($payment);

        return true;
    }


    private function saveTicketData(TicketFormData $data, string $sessionId): void
    {
        $payment = (new Payment())
            ->setSessionId($sessionId)
            ->setCompleted(false)
            ->setCustomer($this->createEntityFromData($data))
            ->setDonation($data->personal->donation);

        $this->em->persist($payment);
        $this->em->flush();
    }

    private function getLineItems(array $tickets, float $donation = null): array
    {
        $lineItems = [];

        if ($donation) {
            $lineItems[] = [
                'price_data' => [
                    'currency' => 'eur',
                    'product_data' => [
                        'name' => 'Spende',
                    ],
                    'unit_amount' => $donation * 100,
                ],
                'quantity' => 1,
            ];
        }

        foreach ($tickets as $ticket) {
            $ticketData = TicketEnum::TICKET_DATA[$ticket->ticketType];
            $lineItems[] = [
                'price_data' => [
                    'currency' => 'eur',
                    'product_data' => [
                        'name' => $ticketData['name'],
                    ],
                    'unit_amount' => $ticketData['price'] * 100,
                ],
                'quantity' => 1,
            ];
        }

        return $lineItems;
    }

    private function createSession(array $lineItems, string $email): Session
    {
        return Session::create([
            'line_items' => $lineItems,
            'mode' => 'payment',
            'customer_email' => $email,
            'success_url' => $this->generator->generate('app_order_success', [], 0) . '?session_id={CHECKOUT_SESSION_ID}',
            'cancel_url' => $this->generator->generate('app_cancelled', [], 0),
        ]);
    }

    private function createEntityFromData(TicketFormData $ticketData): Customer
    {
        $personalData = $ticketData->personal;

        $entity = (new Customer())
            ->setFirstname($personalData->firstname)
            ->setLastname($personalData->lastname)
            ->setEmail($personalData->email)
            ->setPhone($personalData->phone);

        $entity->addTickets($this->createTicketEntities($ticketData->tickets));

        $this->em->persist($entity);
        $this->em->flush();

        return $entity;
    }

    /**
     * @param TicketData[] $tickets
     */
    private function createTicketEntities(array $tickets): array
    {
        $entities = [];

        foreach ($tickets as $ticket) {
            $entities[] = (new Ticket())
                ->setType($ticket->ticketType)
                ->setFoodType($ticket->foodType)
                ->setNote($ticket->note);
        }

        return $entities;
    }
}