<?php

namespace App\Service;

use App\Entity\Advert;
use App\Entity\Facture;
use App\Entity\FactureLine;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

class FactureService
{
    public function __construct(
        private OrderNumberService $orderNumberService,
        private EntityManagerInterface $em,
        private LoggerInterface $logger,
        #[Autowire('%env(APP_SECRET)%')] private string $hmacSecret,
        #[Autowire(env: 'TVA_ENABLED')] private string $tvaEnabled = 'false',
        #[Autowire(env: 'TVA_RATE')] private string $tvaRate = '0.20',
    ) {
    }

    public function isTvaEnabled(): bool
    {
        return 'true' === $this->tvaEnabled || '1' === $this->tvaEnabled;
    }

    public function getTvaRate(): float
    {
        return (float) $this->tvaRate;
    }

    public function create(?Advert $advert = null): Facture
    {
        if (null !== $advert) {
            return $this->createFromAdvert($advert);
        }

        $orderNumber = $this->orderNumberService->generateAndUse();
        $facture = new Facture($orderNumber, $this->hmacSecret);

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

        return $facture;
    }

    public function createFromAdvert(Advert $advert): Facture
    {
        $existingCount = $advert->getFactures()->count();

        $facture = new Facture($advert->getOrderNumber(), $this->hmacSecret);
        $facture->setAdvert($advert);
        $facture->setCustomer($advert->getCustomer());

        // Copie des totaux
        $facture->setTotalHt($advert->getTotalHt());
        $facture->setTotalTva($advert->getTotalTva());
        $facture->setTotalTtc($advert->getTotalTtc());

        if ($existingCount > 0) {
            $facture->setSplitIndex($existingCount + 1);

            $firstFacture = $advert->getFactures()->first();
            if (false !== $firstFacture && 0 === $firstFacture->getSplitIndex()) {
                $firstFacture->setSplitIndex(1);
            }
        }

        // Copie des lignes depuis l'avis
        foreach ($advert->getLines() as $advertLine) {
            $line = new FactureLine(
                $facture,
                $advertLine->getTitle(),
                $advertLine->getPriceHt(),
                $advertLine->getPos(),
            );
            if (null !== $advertLine->getDescription()) {
                $line->setDescription($advertLine->getDescription());
            }
            if (null !== $advertLine->getType()) {
                $line->setType($advertLine->getType());
            }
            if (null !== $advertLine->getServiceId()) {
                $line->setServiceId($advertLine->getServiceId());
            }
            $this->em->persist($line);
            $facture->addLine($line);
        }

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

        $this->logger->info('FactureService: facture '.$facture->getInvoiceNumber().' creee depuis advert '.$advert->getOrderNumber()->getNumOrder());

        return $facture;
    }

    /**
     * Cree une facture depuis un avis dont le paiement est complet.
     * Marque la facture comme payee avec la date et la methode.
     */
    public function createPaidFactureFromAdvert(Advert $advert, string $amount, string $methodLabel): ?Facture
    {
        $advertTotal = (float) $advert->getTotalTtc();
        $paidAmount = (float) $amount;

        // Ne generer la facture que si le montant paye == montant de l'avis
        if (abs($advertTotal - $paidAmount) > 0.01) {
            $this->logger->warning('FactureService: montant paye ('.$amount.') != montant avis ('.$advert->getTotalTtc().') - facture non generee', [
                'advert' => $advert->getOrderNumber()->getNumOrder(),
            ]);

            return null;
        }

        $facture = $this->createFromAdvert($advert);

        // Marquer comme payee
        $facture->setIsPaid(true);
        $facture->setPaidAt(new \DateTimeImmutable());
        $facture->setPaidMethod($methodLabel);
        $facture->setState(Facture::STATE_PAID);

        $this->em->flush();

        $this->logger->info('FactureService: facture '.$facture->getInvoiceNumber().' marquee payee ('.$methodLabel.', '.$amount.' EUR)');

        return $facture;
    }

    /**
     * Calcule les totaux selon la config TVA.
     *
     * @return array{totalHt: string, totalTva: string, totalTtc: string}
     */
    public function computeTotals(string $totalHt): array
    {
        $ht = (float) $totalHt;

        if ($this->isTvaEnabled()) {
            $tva = round($ht * $this->getTvaRate(), 2);
            $ttc = round($ht + $tva, 2);
        } else {
            $tva = 0.0;
            $ttc = $ht;
        }

        return [
            'totalHt' => number_format($ht, 2, '.', ''),
            'totalTva' => number_format($tva, 2, '.', ''),
            'totalTtc' => number_format($ttc, 2, '.', ''),
        ];
    }
}
