<?php

namespace App\Controller;

use App\Entity\Stats;
use App\Entity\CityFollowUp;
use App\Service\Motocultrice;
use App\Service\FollowUpService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class FollowUpController extends AbstractController
{
    private FollowUpService $followUpService;

    public function __construct(FollowUpService $followUpService)
    {
        $this->followUpService = $followUpService;
    }


    #[Route('/admin/followup/{insee_code}/delete', name: 'admin_followup_delete', requirements: ['insee_code' => '\\d+'])]
    public function deleteFollowups(string $insee_code, EntityManagerInterface $em): Response {
        $stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
        if (!$stats) {
            $this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
            return $this->redirectToRoute('app_admin');
        }
        $followups = $stats->getCityFollowUps();
        foreach ($followups as $fu) {
            $em->remove($fu);
        }
        $em->flush();
        $this->addFlash('success', 'Tous les suivis ont été supprimés pour cette ville.');
        return $this->redirectToRoute('admin_followup_graph', ['insee_code' => $insee_code]);
    }

    #[Route('/admin/followup/{insee_code}', name: 'admin_followup', requirements: ['insee_code' => '\\d+'])]
    public function followup(
        string $insee_code,
        Motocultrice $motocultrice,
        EntityManagerInterface $em
    ): Response {
        $stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
        if (!$stats) {
            $this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
            return $this->redirectToRoute('app_admin');
        }
        $this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
        $this->addFlash('success', 'Suivi enregistré pour la ville.');
        return $this->redirectToRoute('admin_followup_graph', ['insee_code' => $insee_code]);
    }

    #[Route('/admin/followup/{insee_code}/graph', name: 'admin_followup_graph', requirements: ['insee_code' => '\\d+'])]
    public function followupGraph(
        string $insee_code,
        EntityManagerInterface $em,
        Motocultrice $motocultrice
    ) {
        $stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
        if (!$stats) {
            $this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
            return $this->redirectToRoute('app_admin');
        }
        $followups = $stats->getCityFollowUps();
        $refresh = false;
        if (!$followups->isEmpty()) {
            $latest = null;
            foreach ($followups as $fu) {
                if ($latest === null || $fu->getDate() > $latest->getDate()) {
                    $latest = $fu;
                }
            }
            if ($latest && $latest->getDate() < (new \DateTime('-1 day'))) {
                $refresh = true;
            }
        } else {
            $refresh = true;
        }
        if ($refresh) {
            $this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
            $followups = $stats->getCityFollowUps();
        }
        $followups = $followups->toArray();
        usort($followups, fn($a, $b) => $a->getDate() <=> $b->getDate());
        $series = [];
        $all_points = [];
        foreach ($followups as $fu) {
            $series[$fu->getName()][] = [
                'date' => $fu->getDate()->format('Y-m-d'),
                'value' => $fu->getMeasure(),
                'name' => $fu->getName(),
            ];
            $all_points[] = [
                'date' => $fu->getDate()->format('Y-m-d'),
                'type' => $fu->getName(),
                'name' => $fu->getName(),
                'value' => $fu->getMeasure(),
            ];
        }
        usort($all_points, fn($a, $b) => strcmp($b['date'], $a['date']));
        $all_points = array_slice($all_points, 0, 20);
        // Tri par date dans chaque série
        foreach ($series as &$points) {
            usort($points, function($a, $b) {
                return strtotime($a['date']) <=> strtotime($b['date']);
            });
        }
        unset($points);
        // Ajout du calcul all_completion_data
        $themes = \App\Service\FollowUpService::getFollowUpThemes();
        $all_completion_data = [];
        $latest_diffs = [];
        // Définir les bornes de période
        $now = new \DateTime();
        $periods = [
            '7j' => (clone $now)->modify('-7 days'),
            '30j' => (clone $now)->modify('-30 days'),
            '6mois' => (clone $now)->modify('-6 months'),
        ];
        foreach ($themes as $type => $label) {
            $all_completion_data[$type] = $series[$type . '_completion'] ?? [];
            $count_series = $series[$type . '_count'] ?? [];
            $completion_series = $series[$type . '_completion'] ?? [];
            // Fonction utilitaire pour trouver la valeur la plus proche avant ou égale à une date
            $findValueAtOrBefore = function($series, \DateTime $date) {
                $val = null;
                foreach (array_reverse($series) as $point) {
                    $ptDate = \DateTime::createFromFormat('Y-m-d', $point['date']);
                    if ($ptDate && $ptDate <= $date) {
                        $val = $point['value'];
                        break;
                    }
                }
                return $val;
            };
            // Valeurs aux bornes
            $val_now = count($count_series) ? $count_series[count($count_series)-1]['value'] : null;
            $val_7j = $findValueAtOrBefore($count_series, $periods['7j']);
            $val_30j = $findValueAtOrBefore($count_series, $periods['30j']);
            $val_6mois = $findValueAtOrBefore($count_series, $periods['6mois']);
            // Différences exclusives
            $diff_7j = ($val_now !== null && $val_7j !== null) ? $val_now - $val_7j : null;
            $diff_30j = ($val_7j !== null && $val_30j !== null) ? $val_7j - $val_30j : null;
            $diff_6mois = ($val_30j !== null && $val_6mois !== null) ? $val_30j - $val_6mois : null;
            // Idem pour la complétion
            $comp_now = count($completion_series) ? $completion_series[count($completion_series)-1]['value'] : null;
            $comp_7j = $findValueAtOrBefore($completion_series, $periods['7j']);
            $comp_30j = $findValueAtOrBefore($completion_series, $periods['30j']);
            $comp_6mois = $findValueAtOrBefore($completion_series, $periods['6mois']);
            $comp_diff_7j = ($comp_now !== null && $comp_7j !== null) ? $comp_now - $comp_7j : null;
            $comp_diff_30j = ($comp_7j !== null && $comp_30j !== null) ? $comp_7j - $comp_30j : null;
            $comp_diff_6mois = ($comp_30j !== null && $comp_6mois !== null) ? $comp_30j - $comp_6mois : null;
            $latest_diffs[$type] = [
                'count_now' => $val_now,
                'count_7j' => $val_7j,
                'count_30j' => $val_30j,
                'count_6mois' => $val_6mois,
                'count_diff_7j' => $diff_7j,
                'count_diff_30j' => $diff_30j,
                'count_diff_6mois' => $diff_6mois,
                'completion_now' => $comp_now,
                'completion_7j' => $comp_7j,
                'completion_30j' => $comp_30j,
                'completion_6mois' => $comp_6mois,
                'completion_diff_7j' => $comp_diff_7j,
                'completion_diff_30j' => $comp_diff_30j,
                'completion_diff_6mois' => $comp_diff_6mois,
                'label' => $label,
            ];
        }
        return $this->render('admin/followup_graph.html.twig', [
            'stats' => $stats,
            'series' => $series,
            'all_points' => $all_points,
            'followup_labels' => FollowUpService::getFollowUpThemes(),
            'followup_icons' => FollowUpService::getFollowUpIcons(),
            'followup_overpass' => FollowUpService::getFollowUpOverpassQueries(),
            'completion_tags' => FollowUpService::getFollowUpCompletionTags(),
            'all_completion_data' => $all_completion_data,
            'latest_diffs' => $latest_diffs,
        ]);
    }

    #[Route('/admin/followup/all', name: 'admin_followup_all')]
    public function followupAll(
        EntityManagerInterface $em,
        Motocultrice $motocultrice
    ) {
        $statsList = $em->getRepository(Stats::class)->findAll();
        foreach ($statsList as $stats) {
            $this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
        }
        $this->addFlash('success', 'Suivi généré pour toutes les villes.');
        return $this->redirectToRoute('app_admin');
    }

    #[Route('/admin/followup/global', name: 'admin_followup_global')]
    public function followupGlobal(EntityManagerInterface $em) {
        $this->followUpService->generateGlobalFollowUps($em);
        $this->addFlash('success', 'Suivi global généré pour toutes les villes.');
        return $this->redirectToRoute('admin_followup_global_graph');
    }

    #[Route('/admin/followup/global/graph', name: 'admin_followup_global_graph')]
    public function followupGlobalGraph(EntityManagerInterface $em) {
        $stats = $em->getRepository(Stats::class)->findOneBy(['zone' => '00000']);
        if (!$stats) {
            $this->addFlash('error', 'Aucun suivi global trouvé.');
            return $this->redirectToRoute('app_admin');
        }
        $followups = $stats->getCityFollowUps();
        $followups = $followups->toArray();
        usort($followups, fn($a, $b) => $a->getDate() <=> $b->getDate());
        $series = [];
        foreach ($followups as $fu) {
            $series[$fu->getName()][] = [
                'date' => $fu->getDate()->format('c'),
                'value' => $fu->getMeasure(),
                'name' => $fu->getName(),
            ];
        }
        // Tri par date dans chaque série
        foreach ($series as &$points) {
            usort($points, function($a, $b) {
                return strtotime($a['date']) <=> strtotime($b['date']);
            });
        }
        unset($points);
        return $this->render('admin/followup_global_graph.html.twig', [
            'stats' => $stats,
            'series' => $series,
            'followup_labels' => FollowUpService::getFollowUpThemes(),
            'followup_icons' => FollowUpService::getFollowUpIcons(),
            'followup_overpass' => FollowUpService::getFollowUpOverpassQueries(),
        ]);
    }

    #[Route('/admin/followup/{insee_code}/embed/{theme}', name: 'admin_followup_embed_graph', requirements: ['insee_code' => '\\d+', 'theme' => '[a-zA-Z0-9_]+'])]
    public function followupEmbedGraph(
        string $insee_code,
        string $theme,
        EntityManagerInterface $em,
        Motocultrice $motocultrice
    ) {
        $stats = $em->getRepository(Stats::class)->findOneBy(['zone' => $insee_code]);
        if (!$stats) {
            $this->addFlash('error', 'Aucune stats trouvée pour ce code INSEE.');
            return $this->redirectToRoute('app_admin');
        }
        $followups = $stats->getCityFollowUps();
        $refresh = false;
        if (!$followups->isEmpty()) {
            $latest = null;
            foreach ($followups as $fu) {
                if ($latest === null || $fu->getDate() > $latest->getDate()) {
                    $latest = $fu;
                }
            }
            if ($latest && $latest->getDate() < (new \DateTime('-1 day'))) {
                $refresh = true;
            }
        } else {
            $refresh = true;
        }
        if ($refresh) {
            $this->followUpService->generateCityFollowUps($stats, $motocultrice, $em);
            $followups = $stats->getCityFollowUps();
        }
        $followups = $followups->toArray();
        usort($followups, fn($a, $b) => $a->getDate() <=> $b->getDate());
        $series = [];
        foreach ($followups as $fu) {
            if (str_starts_with($fu->getName(), $theme)) {
                $series[$fu->getName()][] = [
                    'date' => $fu->getDate()->format('c'),
                    'value' => $fu->getMeasure(),
                    'name' => $fu->getName(),
                ];
            }
        }
        return $this->render('admin/followup_embed_graph.html.twig', [
            'stats' => $stats,
            'series' => $series,
            'theme' => $theme,
            'label' => FollowUpService::getFollowUpThemes()[$theme] ?? $theme,
            'icon' => FollowUpService::getFollowUpIcons()[$theme] ?? 'bi-question-circle',
        ]);
    }
    #[Route('/admin/followup/unused-stores', name: 'admin_followup_unused_stores')]
    public function unusedStores(): Response
    {
        return $this->render('admin/followup_unused_stores.html.twig', [
            'json_url' => 'https://complete-tes-commerces.fr/13/13001-aix-en-provence/json/aix-en-provence_last_stats.json'
        ]);
    }
} 
