<?php

namespace App\Controller\Dashboard;

use App\Logger\AppLogger;
use App\Repository\ContratsPaymentsRepository;
use App\Repository\FactureRepository;
use Doctrine\ORM\QueryBuilder;
use Knp\Component\Pager\PaginatorInterface;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Attribute\Route;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;

#[Route('/crm/facture')]
class FactureController extends AbstractController
{
    public function __construct(
        private readonly ContratsPaymentsRepository $contratsPaymentsRepo,
        private readonly FactureRepository $factureRepository,
        private readonly AppLogger $appLogger,
        private readonly UploaderHelper $uploaderHelper
    ) {
    }

    #[Route('', name: 'app_crm_facture', methods: ['GET'])]
    public function index(Request $request, PaginatorInterface $paginator): Response
    {
        // 1. Récupération des dates et filtres
        [$startDate, $endDate] = $this->getFilterDates($request);
        $searchTerm = $request->query->get('q', '');

        // 2. Construction de la requête
        $queryBuilder = $this->contratsPaymentsRepo->createQueryBuilder('p')
            ->leftJoin('p.contrat', 'c')
            ->leftJoin('c.customer', 'u')
            ->where('p.paymentAt BETWEEN :start AND :end')
            ->setParameter('start', $startDate)
            ->setParameter('end', $endDate)
            ->orderBy('p.paymentAt', 'DESC');

        $queryBuilderFacture = $this->factureRepository->createQueryBuilder('p')
            ->leftJoin('p.contrat', 'c')
            ->leftJoin('c.customer', 'u')
            ->where('p.createAt BETWEEN :start AND :end')
            ->setParameter('start', $startDate)
            ->setParameter('end', $endDate)
            ->orderBy('p.createAt', 'DESC');

        if (!empty($searchTerm)) {
            $queryBuilder->andWhere('u.name LIKE :q OR u.surname LIKE :q OR c.numReservation LIKE :q OR p.type LIKE :q')
                ->setParameter('q', '%' . $searchTerm . '%');
            $queryBuilderFacture->andWhere('u.name LIKE :q OR u.surname LIKE :q OR c.numReservation LIKE :q OR p.type LIKE :q')
                ->setParameter('q', '%' . $searchTerm . '%');
        }

        // 3. Export Excel (Action Rapide)
        if ($request->query->has('extract')) {
            return $this->handleExcelExport($queryBuilder, $request, $startDate, $endDate);
        }

        // 4. Affichage standard
        // (Log optionnel ici si vous souhaitez logger chaque consultation)

        return $this->render('dashboard/contrats/facture.twig', [
            'pagination' => $paginator->paginate($queryBuilder, $request->query->getInt('page', 1), 15),
            'pagination2' => $paginator->paginate($queryBuilderFacture, $request->query->getInt('page', 1), 15),
            'startDate' => $startDate->format('Y-m-d'),
            'endDate' => $endDate->format('Y-m-d'),
            'searchTerm' => $searchTerm,
            'active' => $request->query->get('active', 'facture'),
        ]);
    }

    // --- PRIVATE HELPERS ---

    /**
     * Retourne [Start DateTime, End DateTime] basé sur la requête ou les valeurs par défaut
     */
    private function getFilterDates(Request $request): array
    {
        $startStr = $request->query->get('startDate');
        $endStr = $request->query->get('endDate');

        $start = $startStr ? new \DateTime($startStr . ' 00:00:00') : new \DateTime('first day of this month 00:00:00');
        $end = $endStr ? new \DateTime($endStr . ' 23:59:59') : new \DateTime('last day of this month 23:59:59');

        return [$start, $end];
    }

    /**
     * Gère la logique de récupération des données et déclenche la génération du stream Excel
     */
    private function handleExcelExport(QueryBuilder $qb, Request $request, \DateTime $start, \DateTime $end): Response
    {
        $payments = $qb->getQuery()->getResult();

        // On garde uniquement les paiements validés pour la compta
        $dataToExport = array_filter($payments, fn($p) => $p->getState() === 'complete');

        if (empty($dataToExport)) {
            $this->addFlash('warning', 'Aucune donnée validée à exporter pour cette période.');
            return $this->redirectToRoute('app_crm_facture', [
                'startDate' => $start->format('Y-m-d'),
                'endDate' => $end->format('Y-m-d'),
                'q' => $request->query->get('q')
            ]);
        }

        $this->appLogger->record('EXPORT_EXCEL', sprintf("Export des factures du %s au %s", $start->format('Y-m-d'), $end->format('Y-m-d')));

        return $this->generateExcelStream($dataToExport, $request->getSchemeAndHttpHost(), $start->format('Y-m-d'), $end->format('Y-m-d'));
    }

    /**
     * Génère le fichier Excel physique via StreamedResponse
     */
    private function generateExcelStream(array $payments, string $host, string $startStr, string $endStr): StreamedResponse
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('Export Compta');

        // Styles des en-têtes
        $headers = [
            'A1' => 'DATE PAIEMENT',
            'B1' => 'NOM DU CLIENT',
            'C1' => 'RÉF. RÉSERVATION',
            'D1' => 'MODE DE PAIEMENT',
            'E1' => 'MONTANT TTC',
            'F1' => 'STATUT',
            'G1' => 'LIEN JUSTIFICATIF'
        ];

        foreach ($headers as $cell => $label) {
            $sheet->setCellValue($cell, $label);
            $style = $sheet->getStyle($cell);
            $style->getFont()->setBold(true)->setColor(new Color('FFFFFF'));
            $style->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB('4F46E5');
        }

        $row = 2;
        foreach ($payments as $payment) {
            $contrat = $payment->getContrat();
            $customer = $contrat?->getCustomer();

            $sheet->setCellValue('A' . $row, $payment->getPaymentAt()?->format('d/m/Y H:i') ?? '');
            $sheet->setCellValue('B' . $row, $customer ? strtoupper($customer->getName()) . ' ' . $customer->getSurname() : 'Inconnu');
            $sheet->setCellValue('C' . $row, $contrat?->getNumReservation() ?? 'N/A');
            $sheet->setCellValue('D' . $row, strtoupper($payment->getType()));
            $sheet->setCellValue('E' . $row, $payment->getAmount());
            $sheet->getStyle('E' . $row)->getNumberFormat()->setFormatCode('#,##0.00" €"');
            $sheet->setCellValue('F' . $row, $payment->getState());

            // Lien VichUploader
            $assetPath = $this->uploaderHelper->asset($payment, 'paymentFile');
            if ($assetPath) {
                $sheet->setCellValue('G' . $row, 'Voir le document');
                $sheet->getCell('G' . $row)->getHyperlink()->setUrl($host . $assetPath);
                $sheet->getStyle('G' . $row)->getFont()->setUnderline(true)->setColor(new Color(Color::COLOR_BLUE));
            } else {
                $sheet->setCellValue('G' . $row, 'Aucun fichier');
            }

            $row++;
        }

        foreach (range('A', 'G') as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }

        $writer = new Xlsx($spreadsheet);
        $response = new StreamedResponse(function () use ($writer) {
            $writer->save('php://output');
        });

        $filename = sprintf("compta_export_%s_au_%s.xlsx", $startStr, $endStr);
        $response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        $response->headers->set('Content-Disposition', 'attachment;filename="' . $filename . '"');
        $response->headers->set('Cache-Control', 'max-age=0');

        return $response;
    }
}
