<?php

namespace App\Controller\Admin;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Filesystem\Filesystem;

/**
 * @Route("/annuaire")
 * @IsGranted("ROLE_USER")
 */
class AnnuaireController extends ParentAdminController
{
    private $jsonDirectory;

    public function __construct()
    {
        $this->jsonDirectory = __DIR__ . '/../../../assets/json/';
    }

    /**
     * Liste tous les fichiers JSON de l'annuaire
     * @Route("/", methods="GET", name="annuaire_list")
     */
    public function index(Request $request): Response
    {
        if (!$this->isAnnuaireAuthorized()) {
            return $this->render('bundles/TwigBundle/Exception/error403.html.twig', [], new Response('', Response::HTTP_FORBIDDEN));
        }

        $files = [];
        $jsonFiles = glob($this->jsonDirectory . 'annuaire_*.json');
        
        foreach ($jsonFiles as $file) {
            $filename = basename($file);
            $files[] = [
                'filename' => $filename,
                'name' => str_replace(['annuaire_', '.json'], '', $filename),
                'path' => $file
            ];
        }

        return $this->render('admin/annuaire/list.html.twig', [
            'files' => $files
        ]);
    }

    /**
     * Affiche et permet d'éditer un fichier JSON
     * @Route("/edit/{filename}", methods={"GET", "POST"}, name="annuaire_edit")
     */
    public function edit(Request $request, string $filename): Response
    {
        if (!$this->isAnnuaireAuthorized()) {
            return $this->render('bundles/TwigBundle/Exception/error403.html.twig', [], new Response('', Response::HTTP_FORBIDDEN));
        }

        // Sécuriser le nom du fichier
        $filename = basename($filename);
        if (!preg_match('/^annuaire_[a-zA-Z0-9_]+\.json$/', $filename)) {
            $this->addFlash('error', 'Nom de fichier invalide: ' . $filename);
            return $this->redirectToRoute('annuaire_list');
        }

        $filePath = $this->jsonDirectory . $filename;
        
        if (!file_exists($filePath)) {
            $this->addFlash('error', 'Fichier introuvable: ' . $filePath);
            return $this->redirectToRoute('annuaire_list');
        }

        if ($request->isMethod('POST')) {
            $data = json_decode($request->getContent(), true);
            
            if (json_last_error() !== JSON_ERROR_NONE) {
                return new JsonResponse(['success' => false, 'error' => 'JSON invalide'], Response::HTTP_BAD_REQUEST);
            }

            // Créer une sauvegarde de l'ancienne version
            $backupPath = $filePath . '_old';
            if (file_exists($filePath)) {
                copy($filePath, $backupPath);
            }

            // Sauvegarder le fichier
            $jsonContent = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            file_put_contents($filePath, $jsonContent);

            return new JsonResponse(['success' => true, 'message' => 'Fichier sauvegardé avec succès. Ancienne version sauvegardée dans ' . basename($backupPath)]);
        }

        // Lire le contenu du fichier
        $content = file_get_contents($filePath);
        
        if ($content === false) {
            $this->addFlash('error', 'Impossible de lire le fichier: ' . $filePath);
            return $this->redirectToRoute('annuaire_list');
        }
        
        // Nettoyer le BOM UTF-8 si présent
        $content = preg_replace('/^\xEF\xBB\xBF/', '', $content);
        
        // Normaliser les fins de ligne (convertir \r\n en \n)
        $content = str_replace("\r\n", "\n", $content);
        $content = str_replace("\r", "\n", $content);
        
        // Nettoyer uniquement les caractères de contrôle vraiment problématiques (pas les tabulations ni les newlines)
        // On garde: \t (0x09), \n (0x0A)
        $content = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $content);
        
        // Décoder le JSON
        $data = json_decode($content, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            // Essayer de corriger les erreurs communes
            $originalContent = $content;
            $content = preg_replace('/,\s*}/', '}', $content); // Virgule trailing avant }
            $content = preg_replace('/,\s*]/', ']', $content); // Virgule trailing avant ]
            $data = json_decode($content, true);
            
            if (json_last_error() !== JSON_ERROR_NONE) {
                // Essayer de trouver la ligne approximative de l'erreur
                $errorLine = 1;
                $lines = explode("\n", substr($originalContent, 0, 1000)); // Premiers 1000 caractères
                foreach ($lines as $idx => $line) {
                    $testJson = json_decode(substr($originalContent, 0, strpos($originalContent, $line) + strlen($line)), true);
                    if (json_last_error() !== JSON_ERROR_NONE && json_last_error() !== JSON_ERROR_DEPTH) {
                        $errorLine = $idx + 1;
                        break;
                    }
                }
                
                $errorMsg = 'Erreur JSON dans le fichier: ' . json_last_error_msg() . ' (Code: ' . json_last_error() . '). Erreur probablement autour de la ligne ' . $errorLine;
                $this->addFlash('error', $errorMsg);
                return $this->redirectToRoute('annuaire_list');
            }
        }

        // Vérifier que les données sont un tableau
        if (!is_array($data)) {
            $this->addFlash('error', 'Le fichier JSON doit contenir un tableau. Type reçu: ' . gettype($data));
            return $this->redirectToRoute('annuaire_list');
        }

        // Tester si on peut encoder les données en JSON (pour vérifier qu'il n'y a pas de problème)
        $testJson = json_encode($data, JSON_UNESCAPED_UNICODE);
        if ($testJson === false) {
            $this->addFlash('error', 'Impossible d\'encoder les données en JSON: ' . json_last_error_msg());
            return $this->redirectToRoute('annuaire_list');
        }

        // Vérifier que le tableau n'est pas vide (mais on peut avoir un tableau vide)
        if (!is_array($data)) {
            $this->addFlash('error', 'Les données doivent être un tableau. Type: ' . gettype($data));
            return $this->redirectToRoute('annuaire_list');
        }

        return $this->render('admin/annuaire/edit.html.twig', [
            'filename' => $filename,
            'name' => str_replace(['annuaire_', '.json'], '', $filename),
            'data' => $data
        ]);
    }

    /**
     * Supprime un fichier JSON
     * @Route("/delete/{filename}", methods="DELETE", name="annuaire_delete")
     */
    public function delete(string $filename): JsonResponse
    {
        if (!$this->isAnnuaireAuthorized()) {
            return new JsonResponse(['success' => false, 'error' => 'Accès refusé'], Response::HTTP_FORBIDDEN);
        }

        // Sécuriser le nom du fichier
        $filename = basename($filename);
        if (!preg_match('/^annuaire_[a-zA-Z0-9_]+\.json$/', $filename)) {
            return new JsonResponse(['success' => false, 'error' => 'Nom de fichier invalide'], Response::HTTP_BAD_REQUEST);
        }

        $filePath = $this->jsonDirectory . $filename;
        
        if (!file_exists($filePath)) {
            return new JsonResponse(['success' => false, 'error' => 'Fichier introuvable'], Response::HTTP_NOT_FOUND);
        }

        $filesystem = new Filesystem();
        $filesystem->remove($filePath);

        return new JsonResponse(['success' => true, 'message' => 'Fichier supprimé avec succès']);
    }

    /**
     * Crée un nouveau fichier JSON
     * @Route("/create", methods={"GET", "POST"}, name="annuaire_create")
     */
    public function create(Request $request): Response
    {
        if (!$this->isAnnuaireAuthorized()) {
            return $this->render('bundles/TwigBundle/Exception/error403.html.twig', [], new Response('', Response::HTTP_FORBIDDEN));
        }

        if ($request->isMethod('POST')) {
            $name = $request->request->get('name');
            
            if (empty($name)) {
                $this->addFlash('error', 'Le nom est requis');
                return $this->render('admin/annuaire/create.html.twig');
            }

            // Sécuriser le nom
            $name = preg_replace('/[^a-zA-Z0-9_]/', '', $name);
            $filename = 'annuaire_' . $name . '.json';
            $filePath = $this->jsonDirectory . $filename;

            if (file_exists($filePath)) {
                $this->addFlash('error', 'Un fichier avec ce nom existe déjà');
                return $this->render('admin/annuaire/create.html.twig');
            }

            // Créer un fichier vide avec un tableau JSON vide
            $initialData = [];
            file_put_contents($filePath, json_encode($initialData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));

            $this->addFlash('success', 'Fichier créé avec succès');
            return $this->redirectToRoute('annuaire_edit', ['filename' => $filename]);
        }

        return $this->render('admin/annuaire/create.html.twig');
    }

    /**
     * Vérifie que l'utilisateur connecté est autorisé à gérer les annuaires.
     * Autorisé si :
     *  - rôle id = 1 (super admin)
     *  - OU login = 'v.loriette'
     */
    private function isAnnuaireAuthorized(): bool
    {
        $user = $this->getUser();

        if (!$user) {
            return false;
        }

        $role = method_exists($user, 'getRole') ? $user->getRole() : null;
        $roleId = $role && method_exists($role, 'getId') ? $role->getId() : null;
        $login = method_exists($user, 'getLogin') ? $user->getLogin() : null;

        $isSuperAdmin = ($roleId === 1);
        $isSpecialUser = ($login === 'v.loriette');

        return $isSuperAdmin || $isSpecialUser;
    }
}
