- <?php
- namespace App\Controller;
- use App\Entity\Entreprise;
- use App\Entity\ElectricMeter;
- use App\Form\ElectricMeterType;
- use PhpOffice\PhpSpreadsheet\IOFactory;
- use Doctrine\ORM\EntityManagerInterface;
- use Doctrine\Persistence\ManagerRegistry;
- use PhpOffice\PhpSpreadsheet\Cell\DataType;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpFoundation\Response;
- use Symfony\Component\Routing\Annotation\Route;
- use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
- use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
- use Symfony\Component\HttpFoundation\ResponseHeaderBag;
- use Symfony\Component\HttpFoundation\StreamedResponse;
- class ElectricMeterController extends AbstractController
- {
-     /**
-      * @Route("/entreprise/electric_meter/add/{id}", name="app_electric_meter_add")
-      */
-     public function add(int $id, Request $request, EntityManagerInterface $entityManager): Response
-     {
-         $electric_meters = new ElectricMeter();
-         $electric_meters->setEntrepriseId($id);
-         $form = $this->createForm(ElectricMeterType::class, $electric_meters);
-         $form->handleRequest($request);
-         if ($form->isSubmitted() && $form->isValid()) {
-             $entityManager->persist($electric_meters);
-             $entityManager->flush();
-             
-             // Redirect to the new contract page
-             return $this->redirectToRoute('app_entreprise_new_contrat', [
-                 'id' => $id,
-                 'meterId' => $electric_meters->getId(),
-                 'meterType' => 'electric'
-             ]);
-         }
-         return $this->render('entreprise/electric_meter/add.html.twig', [
-             'electric_meterForm' => $form->createView(),
-             'entreprise_id' => $id
-         ]);
-     }
-     /**
-      * @Route("/entreprise/electric_meter/edit/{id}", name="app_electric_meter_edit")
-      */
-     public function edit(int $id, Request $request, EntityManagerInterface $entityManager, ManagerRegistry $doctrine): Response
-     {
-         $electric_meter = $doctrine->getRepository(ElectricMeter::class)->findOneBy(['id' => $id]);
-         
-         if (!$electric_meter) {
-             throw $this->createNotFoundException('Electric meter not found');
-         }
-         $form = $this->createForm(ElectricMeterType::class, $electric_meter);
-         $form->handleRequest($request);
-         $electric_meter_entity = [ 
-             'adresse_compteur' => $electric_meter->getAdresseCompteur(),
-             'PDL' => $electric_meter->getPDL(),
-             'date_debut' => $electric_meter->getDateDebut() ? date_format($electric_meter->getDateDebut(),"Y-m-d") : "",
-             'date_fin' => $electric_meter->getDateFin() ? date_format($electric_meter->getDateFin(),"Y-m-d") : "",
-             'PS' => $electric_meter->getPS(),
-             'Profil' => $electric_meter->getProfil(),
-             'CAR' => $electric_meter->getCAR(),
-             'fournisseur' => $electric_meter->getFournisseur(),
-             'prix' => $electric_meter->getPrix(),
-         ];
-         if ($form->isSubmitted() && $form->isValid()) {
-             $entityManager->flush();
-             return $this->redirectToRoute('app_entreprise_details',['id' => $electric_meter->getEntrepriseId()]);
-         }
-         return $this->render('entreprise/electric_meter/edit.html.twig', [
-             'electric_meterForm' => $form->createView(),
-             'electric_meter' => $electric_meter_entity,
-             'entreprise_id' => $electric_meter->getEntrepriseId()
-         ]);
-     }
-     /**
-      * @Route("/entreprise/electric_meter/suppr/{id}", name="app_electric_meter_suppr")
-      */
-     public function suppr(int $id, Request $request, EntityManagerInterface $entityManager, ManagerRegistry $doctrine): Response
-     {
-         $electric_meter = $doctrine->getRepository(ElectricMeter::class)->findOneBy(['id' => $id]);
-         
-         if (!$electric_meter) {
-             throw $this->createNotFoundException('Electric meter not found');
-         }
-         $entreprise_id = $electric_meter->getEntrepriseId();
-         $entityManager->remove($electric_meter);
-         $entityManager->flush();
-         return $this->redirectToRoute('app_entreprise_details',['id' => $entreprise_id]);
-     }
-     /**
-      * @Route("/entreprise/electric_meter/check_pdl/{pdl}", name="app_electric_meter_check_pdl")
-      */
-     public function checkPDL($pdl, ManagerRegistry $doctrine): Response
-     {
-         $electric_meter = $doctrine->getRepository(ElectricMeter::class)->findOneBy(['PDL' => $pdl]);
-         if($electric_meter){
-             return new Response("exist");
-         }
-         return new Response("available");
-     }
-     private function normalizeToKVA($raw): ?float
-     {
-         if ($raw === null || $raw === '') return null;
-         $s = (string)$raw;
-         // uniformiser
-         $s = str_replace(["\xC2\xA0", ' '], '', $s);   // supprime espaces/nbsp
-         $unit = 'KVA';
-         // détecte unité (VA/kVA/MVA) puis isole la partie numérique
-         if (preg_match('/^\s*([\d\.,]+)\s*([a-zA-Z]*)\s*$/u', $s, $m)) {
-             $num  = str_replace(',', '.', $m[1]); // virgule → point
-             $unit = strtoupper($m[2] ?? 'KVA');
-             if (!is_numeric($num)) return null;
-             $val = (float)$num;
-             // conversion en kVA
-             switch ($unit) {
-                 case 'MVA': return $val * 1000.0;
-                 case 'KVA': return $val;
-                 case 'VA':  return $val / 1000.0;
-                 default:    return $val; // si pas d’unité, on considère déjà en kVA
-             }
-         }
-         // si juste un nombre brut
-         $s = str_replace(',', '.', $s);
-         return is_numeric($s) ? (float)$s : null;
-     }
-     /**
-      * @Route(
-      *   "/entreprise/electric_meter/generate_study/{pdl}/{type}",
-      *   name="app_electric_meter_generate_study",
-      *   requirements={"type"="C5|C4|C3|C2|C1"}
-      * )
-      */
-     public function generateStudy(string $pdl, string $type, ManagerRegistry $doctrine): StreamedResponse
-     {
-         // --- Récupération des entités
-         $electricMeter = $doctrine->getRepository(ElectricMeter::class)->findOneBy(['PDL' => $pdl]);
-         if (!$electricMeter) {
-             throw $this->createNotFoundException('Electric meter not found');
-         }
-         $entreprise = $doctrine->getRepository(Entreprise::class)->find($electricMeter->getEntrepriseId());
-         if (!$entreprise) {
-             throw $this->createNotFoundException('Entreprise not found');
-         }
-         // --- Normalisation du type (C3/C2/C1 => C3_C2_C1)
-         $normalizedType = in_array($type, ['C3','C2','C1'], true) ? 'C3_C2_C1' : $type;
-         // --- Choix du template
-         $base = $this->getParameter('kernel.project_dir') . '/assets/templates';
-         $TEMPLATE_BY_TYPE = [
-             'C5'        => $base . '/Etude_C5.xlsx',
-             'C4'        => $base . '/Etude_C4.xlsx',
-             'C3_C2_C1'  => $base . '/Etude_C3_C2_C1.xlsx',
-         ];
-         $templatePath = $TEMPLATE_BY_TYPE[$normalizedType] ?? null;
-         if (!$templatePath || !is_file($templatePath)) {
-             throw new \RuntimeException(sprintf('Template introuvable pour le type %s', $normalizedType));
-         }
-         // --- Parsing adresse (voie / CP / ville) robuste
-         $address     = (string) ($electricMeter->getAdresseCompteur() ?? '');
-         $postalCode  = '';
-         $city        = '';
-         $street      = '';
-         if (preg_match('/\b(\d{5})\b(?:\s+(.+))?$/u', $address, $m, PREG_OFFSET_CAPTURE)) {
-             $postalCode = $m[1][0] ?? '';
-             $city       = isset($m[2][0]) ? trim($m[2][0]) : '';
-             $cpPos      = $m[1][1]; // offset du CP dans la chaîne complète
-             $street     = trim(mb_substr($address, 0, $cpPos));
-         } else {
-             $street = $address;
-         }
-         // --- Copier le template vers un fichier temporaire
-         $tempFile = tempnam(sys_get_temp_dir(), 'excel_');
-         if ($tempFile === false) {
-             throw new \RuntimeException('Impossible de créer un fichier temporaire.');
-         }
-         if (!@copy($templatePath, $tempFile)) {
-             @unlink($tempFile);
-             throw new \RuntimeException('Copie du template échouée.');
-         }
-         $ps      = $electricMeter->getPS() ?? '';
-         $psRaw = $electricMeter->getPS();
-         $psKVA = $this->normalizeToKVA($psRaw);
-         $reader = IOFactory::createReader('Xlsx');
-         $reader->setReadDataOnly(false);
-         $reader->setIncludeCharts(true);
-         
-         $spreadsheet = $reader->load($tempFile);
-         $sheet = $spreadsheet->getActiveSheet();
-         $raison  = (string) ($entreprise->getRaisonSociale() ?? '');
-         $siret   = (string) ($entreprise->getSIRET() ?? '');
-         $pdlVal  = (string) ($electricMeter->getPDL() ?? '');
-         $profil  = (string) ($electricMeter->getProfil() ?? '');
-         $nafRaw  = (string) ($entreprise->getNaf() ?? '');
-         $nafNum  = preg_replace('/\D+/', '', $nafRaw);
-         $nafBig  = (int) $nafNum > 4500 ? 'Oui' : 'Non';
-         $dateFin = $electricMeter->getDateFin() ? $electricMeter->getDateFin()->format('d/m/Y') : '';
-         switch ($normalizedType) {
-             case 'C3_C2_C1':
-                 $sheet->setCellValue('A1', $raison);
-                 $sheet->setCellValueExplicit('B4', $siret, DataType::TYPE_STRING);
-                 $sheet->setCellValueExplicit('B5', $pdlVal, DataType::TYPE_STRING);
-                 foreach (['B9','C9','D9','E9','F9'] as $cell) {
-                     $sheet->setCellValue($cell, $psKVA);
-                     $sheet->getStyle($cell)->getNumberFormat()->setFormatCode('#,##0.## "kVA"');
-                 }
-                 $sheet->setCellValue('B10', $profil);
-                 $sheet->setCellValue('B6', $address);
-                 $sheet->setCellValueExplicit('J4', $nafRaw, DataType::TYPE_STRING);
-                 $sheet->setCellValue('J5', $nafBig);
-                 $sheet->setCellValue('J7', $dateFin);
-                 break;
-             case 'C4':
-                 $sheet->setCellValue('A3', $raison);
-                 $sheet->setCellValueExplicit('B6', $siret, DataType::TYPE_STRING);
-                 $sheet->setCellValueExplicit('B7', $pdlVal, DataType::TYPE_STRING);
-                 $sheet->setCellValue('B8', $psKVA);
-                 $sheet->getStyle('B8')->getNumberFormat()->setFormatCode('#,##0.## "kVA"');
-                 $sheet->setCellValue('B16', $address);
-                 $sheet->setCellValueExplicit('G6', $nafRaw, DataType::TYPE_STRING);
-                 $sheet->setCellValue('G7', $nafBig);
-                 $sheet->setCellValue('G9', $dateFin);
-                 break;
-             case 'C5':
-                 $sheet->setCellValue('A3', $raison);
-                 $sheet->setCellValueExplicit('B6', $siret, DataType::TYPE_STRING);
-                 $sheet->setCellValueExplicit('B7', $pdlVal, DataType::TYPE_STRING);
-                 $sheet->setCellValue('B8', $psKVA);
-                 $sheet->getStyle('B8')->getNumberFormat()->setFormatCode('#,##0.## "kVA"');
-                 $sheet->setCellValue('B16', $address);
-                 $sheet->setCellValueExplicit('G6', $nafRaw, DataType::TYPE_STRING);
-                 $sheet->setCellValue('G7', $nafBig);
-                 $sheet->setCellValue('G9', $dateFin);
-                 break;
-         }
-         // --- Écriture du fichier au même endroit temporaire (préserve formules & graphiques)
-         $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
-         $writer->setOffice2003Compatibility(false);
-         $writer->setPreCalculateFormulas(false);
-         $writer->setIncludeCharts(true);
-         $writer->save($tempFile);
-         // --- Préparer un nom de fichier propre (accents/espaces)
-         $rawName  = $raison !== '' ? $raison : 'unknown';
-         $ascii    = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $rawName) ?: $rawName;
-         $ascii    = preg_replace('/[^\w\-]+/u', '_', $ascii);
-         // On garde le type tel que demandé dans l’URL (C5|C4|C3|C2|C1)
-         $studyLabel = $type;
-         // 4 derniers chiffres du PDL
-         $pdlLast4 = $pdlVal !== '' ? substr($pdlVal, -4) : '0000';
-         // Timestamp lisible (Europe/Paris)
-         $stamp = (new \DateTime('now', new \DateTimeZone('Europe/Paris')))->format('dmY');
-         // Résultat : Etude_C5_1234_Flex_Energie-20250925-223015.xlsx
-         $filename = sprintf('Etude_%s-%s-%s-%s.xlsx', $studyLabel, $pdlLast4, $ascii, $stamp);
-         // --- StreamedResponse (gestion mémoire + cleanup même en cas d’erreur)
-         $response = new StreamedResponse(function () use ($tempFile) {
-             $out = fopen('php://output', 'wb');
-             $in  = fopen($tempFile, 'rb');
-             try {
-                 stream_copy_to_stream($in, $out);
-             } finally {
-                 if (is_resource($in))  fclose($in);
-                 if (is_resource($out)) fclose($out);
-                 @unlink($tempFile);
-             }
-         });
-         $response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
-         $response->headers->set('Cache-Control', 'max-age=0, private');
-         $response->headers->set('Pragma', 'public');
-         $response->headers->set('X-Accel-Buffering', 'no'); // no-op si non supporté
-         $response->setStatusCode(200);
-         $response->headers->set(
-             'Content-Disposition',
-             $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename)
-         );
-         return $response;
-     }
- }
-