<?php

namespace App\Service;

use App\Entity\BilletBuyer;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Dompdf\Dompdf;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Twig\Environment;

class ExportService
{
    public function __construct(
        private EntityManagerInterface $em,
        private Environment $twig,
        #[Autowire('%stripe_fee_rate%')] private float $stripeFeeRate = 0.015,
        #[Autowire('%stripe_fee_fixed%')] private int $stripeFeeFixed = 25,
    ) {
    }

    /**
     * @codeCoverageIgnore Requires database queries
     *
     * @return array{orders: list<BilletBuyer>, totalHT: float, commissionEticket: float, commissionStripe: float, netOrga: float}
     */
    public function getMonthlyStats(int $year, int $month, ?User $organizer = null): array
    {
        $start = new \DateTimeImmutable("$year-$month-01 00:00:00");
        $end = $start->modify('last day of this month')->setTime(23, 59, 59);

        $qb = $this->em->createQueryBuilder()
            ->select('o', 'i')
            ->from(BilletBuyer::class, 'o')
            ->leftJoin('o.items', 'i')
            ->where('o.status = :paid')
            ->andWhere('o.paidAt >= :start')
            ->andWhere('o.paidAt <= :end')
            ->setParameter('paid', BilletBuyer::STATUS_PAID)
            ->setParameter('start', $start)
            ->setParameter('end', $end)
            ->orderBy('o.paidAt', 'ASC');

        if ($organizer) {
            $qb->join('o.event', 'e')
                ->andWhere('e.account = :orga')
                ->setParameter('orga', $organizer);
        }

        $orders = $qb->getQuery()->getResult();

        $totalHT = 0;
        $commissionEticket = 0;
        $commissionStripe = 0;

        foreach ($orders as $order) {
            $ht = $order->getTotalHT() / 100;
            $rate = $order->getEvent()->getAccount()->getCommissionRate() ?? 3;
            $totalHT += $ht;
            $commissionEticket += $ht * ($rate / 100);
            $commissionStripe += $ht * $this->stripeFeeRate + $this->stripeFeeFixed / 100;
        }

        return [
            'orders' => $orders,
            'totalHT' => $totalHT,
            'commissionEticket' => $commissionEticket,
            'commissionStripe' => $commissionStripe,
            'netOrga' => $totalHT - $commissionEticket - $commissionStripe,
        ];
    }

    /**
     * @param list<BilletBuyer> $orders
     */
    public function generateCsv(array $orders, bool $isAdmin = false): string
    {
        $lines = [];

        if ($isAdmin) {
            $lines[] = implode(';', ['Commande', 'Date', 'Evenement', 'Organisateur', 'Acheteur', 'Email', 'Billets', 'Total HT', 'Com E-Ticket', 'Com Stripe']);
        } else {
            $lines[] = implode(';', ['Commande', 'Date', 'Evenement', 'Acheteur', 'Email', 'Billets', 'Total HT', 'Com E-Ticket', 'Com Stripe', 'Net percu']);
        }

        foreach ($orders as $order) {
            $ht = $order->getTotalHT() / 100;
            $rate = $order->getEvent()->getAccount()->getCommissionRate() ?? 3;
            $eticketFee = $ht * ($rate / 100);
            $stripeFee = $ht * $this->stripeFeeRate + $this->stripeFeeFixed / 100;
            $net = $ht - $eticketFee - $stripeFee;

            $items = [];
            foreach ($order->getItems() as $item) {
                $items[] = $item->getBilletName().' x'.$item->getQuantity();
            }

            if ($isAdmin) {
                $lines[] = implode(';', [
                    $order->getOrderNumber(),
                    $order->getPaidAt()?->format('d/m/Y H:i'),
                    $order->getEvent()->getTitle(),
                    $order->getEvent()->getAccount()->getCompanyName() ?? $order->getEvent()->getAccount()->getFirstName(),
                    $order->getFirstName().' '.$order->getLastName(),
                    $order->getEmail(),
                    implode(', ', $items),
                    number_format($ht, 2, ',', ''),
                    number_format($eticketFee, 2, ',', ''),
                    number_format($stripeFee, 2, ',', ''),
                ]);
            } else {
                $lines[] = implode(';', [
                    $order->getOrderNumber(),
                    $order->getPaidAt()?->format('d/m/Y H:i'),
                    $order->getEvent()->getTitle(),
                    $order->getFirstName().' '.$order->getLastName(),
                    $order->getEmail(),
                    implode(', ', $items),
                    number_format($ht, 2, ',', ''),
                    number_format($eticketFee, 2, ',', ''),
                    number_format($stripeFee, 2, ',', ''),
                    number_format(max(0, $net), 2, ',', ''),
                ]);
            }
        }

        return implode("\n", $lines);
    }

    /**
     * @param array{orders: list<BilletBuyer>, totalHT: float, commissionEticket: float, commissionStripe: float, netOrga: float} $stats
     */
    public function generatePdf(array $stats, int $year, int $month, ?User $organizer = null): string
    {
        $html = $this->twig->render('pdf/export_recap.html.twig', [
            'stats' => $stats,
            'year' => $year,
            'month' => $month,
            'organizer' => $organizer,
            'isAdmin' => null === $organizer,
        ]);

        $dompdf = new Dompdf();
        $dompdf->loadHtml($html);
        $dompdf->setPaper('A4', 'landscape');
        $dompdf->render();

        return $dompdf->output();
    }
}
