<?php

namespace App\Controller;

use App\Entity\Stats;
use App\Repository\StatsRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ApiController extends AbstractController
{
    #[Route('/api/v1/stats_geojson', name: 'api_stats_geojson', methods: ['GET'])]
    public function statsGeojson(StatsRepository $statsRepository): JsonResponse
    {
        $statsList = $statsRepository->findAll();
        $features = [];
        foreach ($statsList as $stats) {
            // Calcul du barycentre des commerces de la zone
            $lat = null;
            $lon = null;
            $places = $stats->getPlaces();
            $count = 0;
            $sumLat = 0;
            $sumLon = 0;
            foreach ($places as $place) {
                if ($place->getLat() && $place->getLon()) {
                    $sumLat += $place->getLat();
                    $sumLon += $place->getLon();
                    $count++;
                }
            }
            if ($count > 0) {
                $lat = $sumLat / $count;
                $lon = $sumLon / $count;
            }
            $feature = [
                'type' => 'Feature',
                'geometry' => $lat && $lon ? [
                    'type' => 'Point',
                    'coordinates' => [$lon, $lat],
                ] : null,
                'properties' => [
                    'id' => $stats->getId(),
                    'name' => $stats->getName(),
                    'zone' => $stats->getZone(),
                    'completion_percent' => $stats->getCompletionPercent(),
                    'places_count' => $stats->getPlacesCount(),
                    'avec_horaires' => $stats->getAvecHoraires(),
                    'avec_adresse' => $stats->getAvecAdresse(),
                    'avec_site' => $stats->getAvecSite(),
                    'avec_accessibilite' => $stats->getAvecAccessibilite(),
                    'avec_note' => $stats->getAvecNote(),
                    'population' => $stats->getPopulation(),
                    'siren' => $stats->getSiren(),
                    'codeEpci' => $stats->getCodeEpci(),
                    'codesPostaux' => $stats->getCodesPostaux(),
                    'date_created' => $stats->getDateCreated() ? $stats->getDateCreated()->format('c') : null,
                    'date_modified' => $stats->getDateModified() ? $stats->getDateModified()->format('c') : null,
                ],
            ];
            $features[] = $feature;
        }
        $geojson = [
            'type' => 'FeatureCollection',
            'features' => $features,
            'meta' => [
                'generated_at' => (new \DateTime())->format('c'),
                'source' => 'https://osm-commerces.cipherbliss.com/api/v1/stats_geojson'
            ]
        ];
        return new JsonResponse($geojson, Response::HTTP_OK, [
            'Content-Type' => 'application/geo+json'
        ]);
    }

    #[Route('/api/v1/stats/{insee}', name: 'api_stats_by_insee', methods: ['GET'])]
    public function statsByInsee(StatsRepository $statsRepository, string $insee): JsonResponse
    {
        $stats = $statsRepository->findOneBy(['zone' => $insee]);
        if (!$stats) {
            return new JsonResponse(['error' => 'Zone non trouvée'], Response::HTTP_NOT_FOUND);
        }
        $data = [
            'id' => $stats->getId(),
            'name' => $stats->getName(),
            'zone' => $stats->getZone(),
            'completion_percent' => $stats->getCompletionPercent(),
            'places_count' => $stats->getPlacesCount(),
            'avec_horaires' => $stats->getAvecHoraires(),
            'avec_adresse' => $stats->getAvecAdresse(),
            'avec_site' => $stats->getAvecSite(),
            'avec_accessibilite' => $stats->getAvecAccessibilite(),
            'avec_note' => $stats->getAvecNote(),
            'population' => $stats->getPopulation(),
            'siren' => $stats->getSiren(),
            'codeEpci' => $stats->getCodeEpci(),
            'codesPostaux' => $stats->getCodesPostaux(),
            'date_created' => $stats->getDateCreated() ? $stats->getDateCreated()->format('c') : null,
            'date_modified' => $stats->getDateModified() ? $stats->getDateModified()->format('c') : null,
        ];
        return new JsonResponse($data, Response::HTTP_OK);
    }

    #[Route('/api/v1/stats/{insee}/places', name: 'api_stats_places_by_insee', methods: ['GET'])]
    public function statsPlacesByInsee(StatsRepository $statsRepository, string $insee): JsonResponse
    {
        $stats = $statsRepository->findOneBy(['zone' => $insee]);
        if (!$stats) {
            return new JsonResponse(['error' => 'Zone non trouvée'], Response::HTTP_NOT_FOUND);
        }
        $features = [];
        foreach ($stats->getPlaces() as $place) {
            $lat = $place->getLat();
            $lon = $place->getLon();
            $feature = [
                'type' => 'Feature',
                'geometry' => ($lat && $lon) ? [
                    'type' => 'Point',
                    'coordinates' => [$lon, $lat],
                ] : null,
                'properties' => [
                    'id' => $place->getId(),
                    'name' => $place->getName(),
                    'main_tag' => $place->getMainTag(),
                    'osmId' => $place->getOsmId(),
                    'email' => $place->getEmail(),
                    'note' => $place->getNote(),
                    'zip_code' => $place->getZipCode(),
                    'siret' => $place->getSiret(),
                    'has_opening_hours' => $place->hasOpeningHours(),
                    'has_address' => $place->hasAddress(),
                    'has_website' => $place->hasWebsite(),
                    'has_wheelchair' => $place->hasWheelchair(),
                    'has_note' => $place->hasNote(),
                    'completion_percent' => $place->getCompletionPercentage(),
                ],
            ];
            $features[] = $feature;
        }
        $geojson = [
            'type' => 'FeatureCollection',
            'features' => $features,
            'meta' => [
                'generated_at' => (new \DateTime())->format('c'),
                'source' => 'https://osm-commerces.cipherbliss.com/api/v1/stats/by_insee/' . $insee . '/places'
            ]
        ];
        return new JsonResponse($geojson, Response::HTTP_OK, [
            'Content-Type' => 'application/geo+json'
        ]);
    }

    #[Route('/api/v1/stats/by_insee/{insee}/places.csv', name: 'api_stats_places_csv_by_insee', methods: ['GET'])]
    public function statsPlacesCsvByInsee(StatsRepository $statsRepository, string $insee): StreamedResponse
    {
        $stats = $statsRepository->findOneBy(['zone' => $insee]);
        if (!$stats) {
            $response = new StreamedResponse();
            $response->setCallback(function() {
                echo 'error\nZone non trouvée';
            });
            $response->headers->set('Content-Type', 'text/csv');
            $response->setStatusCode(Response::HTTP_NOT_FOUND);
            return $response;
        }
        $response = new StreamedResponse(function() use ($stats) {
            $handle = fopen('php://output', 'w');
            // En-têtes CSV
            fputcsv($handle, [
                'id', 'name', 'main_tag', 'osmId', 'email', 'note', 'zip_code', 'siret', 'lat', 'lon', 'has_opening_hours', 'has_address', 'has_website', 'has_wheelchair', 'has_note'
            ]);
            foreach ($stats->getPlaces() as $place) {
                fputcsv($handle, [
                    $place->getId(),
                    $place->getName(),
                    $place->getMainTag(),
                    $place->getOsmId(),
                    $place->getEmail(),
                    $place->getNote(),
                    $place->getZipCode(),
                    $place->getSiret(),
                    $place->getLat(),
                    $place->getLon(),
                    $place->hasOpeningHours(),
                    $place->hasAddress(),
                    $place->hasWebsite(),
                    $place->hasWheelchair(),
                    $place->hasNote(),
                    $place->getCompletionPercentage(),
                ]);
            }
            fclose($handle);
        });
        $response->headers->set('Content-Type', 'text/csv');
        $response->headers->set('Content-Disposition', 'attachment; filename="places_'.$insee.'.csv"');
        return $response;
    }

    #[Route('/api/v1/stats/export', name: 'api_stats_export', methods: ['GET'])]
    public function statsExport(
        StatsRepository $statsRepository,
        \Symfony\Component\HttpFoundation\Request $request
    ): JsonResponse {
        // Récupérer les paramètres de requête
        $zone = $request->query->get('zone');
        $pretty = $request->query->getBoolean('pretty', false);
        $includeFollowups = $request->query->getBoolean('include_followups', true);
        $includePlaces = $request->query->getBoolean('include_places', false);

        try {
            // Construire la requête
            $qb = $statsRepository->createQueryBuilder('s');
            
            if ($zone) {
                $qb->where('s.zone = :zone')
                   ->setParameter('zone', $zone);
            }

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

            if (empty($stats)) {
                return new JsonResponse([
                    'error' => 'Aucun objet Stats trouvé',
                    'message' => $zone ? "Aucune zone trouvée pour le code INSEE: $zone" : 'Aucune donnée disponible'
                ], Response::HTTP_NOT_FOUND);
            }

            // Préparer les données pour l'export
            $exportData = [];
            
            foreach ($stats as $stat) {
                $statData = [
                    'id' => $stat->getId(),
                    'zone' => $stat->getZone(),
                    'name' => $stat->getName(),
                    'dateCreated' => $stat->getDateCreated() ? $stat->getDateCreated()->format('Y-m-d H:i:s') : null,
                    'dateModified' => $stat->getDateModified() ? $stat->getDateModified()->format('Y-m-d H:i:s') : null,
                    'population' => $stat->getPopulation(),
                    'budgetAnnuel' => $stat->getBudgetAnnuel(),
                    'siren' => $stat->getSiren(),
                    'codeEpci' => $stat->getCodeEpci(),
                    'codesPostaux' => $stat->getCodesPostaux(),
                    'decomptes' => [
                        'placesCount' => $stat->getPlacesCount(),
                        'avecHoraires' => $stat->getAvecHoraires(),
                        'avecAdresse' => $stat->getAvecAdresse(),
                        'avecSite' => $stat->getAvecSite(),
                        'avecAccessibilite' => $stat->getAvecAccessibilite(),
                        'avecNote' => $stat->getAvecNote(),
                        'completionPercent' => $stat->getCompletionPercent(),
                        'placesCountReal' => $stat->getPlaces()->count(),
                    ],
                ];

                // Ajouter les followups si demandé
                if ($includeFollowups) {
                    $statData['followups'] = [];
                    foreach ($stat->getCityFollowUps() as $followup) {
                        $statData['followups'][] = [
                            'name' => $followup->getName(),
                            'measure' => $followup->getMeasure(),
                            'date' => $followup->getDate()->format('Y-m-d H:i:s')
                        ];
                    }
                }

                // Ajouter les lieux si demandé
                if ($includePlaces) {
                    $statData['places'] = [];
                    foreach ($stat->getPlaces() as $place) {
                        $statData['places'][] = [
                            'id' => $place->getId(),
                            'name' => $place->getName(),
                            'mainTag' => $place->getMainTag(),
                            'osmId' => $place->getOsmId(),
                            'osmKind' => $place->getOsmKind(),
                            'email' => $place->getEmail(),
                            'note' => $place->getNote(),
                            'zipCode' => $place->getZipCode(),
                            'siret' => $place->getSiret(),
                            'lat' => $place->getLat(),
                            'lon' => $place->getLon(),
                            'hasOpeningHours' => $place->hasOpeningHours(),
                            'hasAddress' => $place->hasAddress(),
                            'hasWebsite' => $place->hasWebsite(),
                            'hasWheelchair' => $place->hasWheelchair(),
                            'hasNote' => $place->hasNote(),
                            'completionPercentage' => $place->getCompletionPercentage(),
                        ];
                    }
                }

                $exportData[] = $statData;
            }

            // Préparer le JSON
            $jsonOptions = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
            if ($pretty) {
                $jsonOptions |= JSON_PRETTY_PRINT;
            }

            $jsonContent = json_encode($exportData, $jsonOptions);

            if (json_last_error() !== JSON_ERROR_NONE) {
                return new JsonResponse([
                    'error' => 'Erreur lors de l\'encodage JSON',
                    'message' => json_last_error_msg()
                ], Response::HTTP_INTERNAL_SERVER_ERROR);
            }

            // Retourner la réponse
            $response = new JsonResponse($exportData, Response::HTTP_OK);
            $response->headers->set('Content-Type', 'application/json');
            $response->headers->set('Content-Disposition', 'attachment; filename="stats_export.json"');
            
            // Ajouter des métadonnées dans les headers
            $response->headers->set('X-Export-Count', count($stats));
            $response->headers->set('X-Export-Generated', (new \DateTime())->format('c'));
            if ($zone) {
                $response->headers->set('X-Export-Zone', $zone);
            }

            return $response;

        } catch (\Exception $e) {
            return new JsonResponse([
                'error' => 'Erreur lors de l\'export',
                'message' => $e->getMessage()
            ], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
} 