<?php

declare(strict_types=1);

namespace App\Controllers;

require_once __DIR__ . '/../Services/LogService.php';
require_once __DIR__ . '/../Services/EventLogService.php';
require_once __DIR__ . '/../Services/ApiService.php';

use PDO;
use PDOException;
use Database;
use AppConfig;
use Request;
use Response;
use Session;
use App\Services\LogService;
use App\Services\EventLogService;
use App\Services\ApiService;
use App\Services\FileService;
use Exception;

class EntiteController {
    private PDO $db;
    private AppConfig $appConfig;

    public function __construct() {
        $this->db = Database::getInstance();
        $this->appConfig = AppConfig::getInstance();
    }

    /**
     * Crée une nouvelle entité (amicale) si elle n'existe pas déjà avec le code postal spécifié
     * 
     * @param string $name Nom de l'amicale
     * @param string $postalCode Code postal
     * @param string $cityName Nom de la ville
     * @return array|false Tableau contenant l'ID de l'entité créée ou false en cas d'erreur
     * @throws Exception Si une entité existe déjà avec ce code postal
     */
    public function createEntite(string $name, string $postalCode, string $cityName): array|false {
        try {
            // Vérification que le code postal n'existe pas déjà
            $stmt = $this->db->prepare('SELECT id FROM entites WHERE code_postal = ?');
            $stmt->execute([$postalCode]);

            if ($stmt->fetch()) {
                throw new Exception('Une amicale existe déjà sur ce code postal');
            }

            // Chiffrement du nom
            $encryptedName = ApiService::encryptData($name);

            // Insertion de la nouvelle entité
            $stmt = $this->db->prepare('
                INSERT INTO entites (
                    encrypted_name,
                    code_postal,
                    ville,
                    fk_type,
                    created_at,
                    chk_active,
                    chk_user_delete_pass
                ) VALUES (?, ?, ?, 1, NOW(), 1, 0)
            ');

            $stmt->execute([
                $encryptedName,
                $postalCode,
                $cityName
            ]);

            $entiteId = $this->db->lastInsertId();

            if (!$entiteId) {
                throw new Exception('Erreur lors de la création de l\'entité');
            }

            // Log de création de l'entité
            EventLogService::logEntityCreated(
                (int)$entiteId,
                1, // fk_type toujours à 1 dans cette méthode
                $postalCode
            );

            return [
                'id' => $entiteId,
                'name' => $name,
                'postalCode' => $postalCode,
                'cityName' => $cityName
            ];
        } catch (Exception $e) {
            LogService::log('Erreur lors de la création de l\'entité GeoSector', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'name' => $name,
                'postalCode' => $postalCode,
                'cityName' => $cityName
            ]);

            throw $e;
        }
    }

    /**
     * Récupère une entité par son ID
     * 
     * @param int $id ID de l'entité
     * @return array|false Données de l'entité ou false si non trouvée
     */
    public function getEntiteById(int $id): array|false {
        try {
            $stmt = $this->db->prepare('
                SELECT id, encrypted_name, code_postal, ville, fk_type, chk_active, chk_user_delete_pass
                FROM entites
                WHERE id = ? AND chk_active = 1
            ');

            $stmt->execute([$id]);
            $entite = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$entite) {
                return false;
            }

            // Déchiffrement du nom
            $entite['name'] = ApiService::decryptData($entite['encrypted_name']);
            unset($entite['encrypted_name']);

            return $entite;
        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération de l\'entité GeoSector', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'id' => $id
            ]);

            return false;
        }
    }

    /**
     * Récupère une entité par son code postal
     * 
     * @param string $postalCode Code postal
     * @return array|false Données de l'entité ou false si non trouvée
     */
    public function getEntiteByPostalCode(string $postalCode): array|false {
        try {
            $stmt = $this->db->prepare('
                SELECT id, encrypted_name, code_postal, ville, fk_type, chk_active, chk_user_delete_pass
                FROM entites
                WHERE code_postal = ? AND chk_active = 1
            ');

            $stmt->execute([$postalCode]);
            $entite = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$entite) {
                return false;
            }

            // Déchiffrement du nom
            $entite['name'] = ApiService::decryptData($entite['encrypted_name']);
            unset($entite['encrypted_name']);

            return $entite;
        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération de l\'entité GeoSector par code postal', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'postalCode' => $postalCode
            ]);

            return false;
        }
    }

    /**
     * Vérifie si une entité existe avec le code postal spécifié, et en crée une nouvelle si nécessaire
     * 
     * @param string $name Nom de l'amicale
     * @param string $postalCode Code postal
     * @return int ID de l'entité créée ou existante
     * @throws Exception Si une entité existe déjà avec ce code postal
     */
    public function getOrCreateEntiteByPostalCode(string $name, string $postalCode): int {
        try {
            // Vérification que le code postal n'existe pas déjà
            $stmt = $this->db->prepare('SELECT COUNT(*) as count FROM entites WHERE code_postal = ?');
            $stmt->execute([$postalCode]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($result && $result['count'] > 0) {
                throw new Exception('Une amicale est déjà inscrite à ce code postal');
            }

            // Chiffrement du nom
            $encryptedName = ApiService::encryptData($name);

            // Insertion de la nouvelle entité
            $stmt = $this->db->prepare('
                INSERT INTO entites (
                    encrypted_name,
                    code_postal,
                    ville,
                    fk_type,
                    created_at,
                    chk_active
                ) VALUES (?, ?, "", 1, NOW(), 1)
            ');

            $stmt->execute([
                $encryptedName,
                $postalCode
            ]);

            $entiteId = (int)$this->db->lastInsertId();

            if (!$entiteId) {
                throw new Exception('Erreur lors de la création de l\'entité');
            }

            // Log de création de l'entité
            EventLogService::logEntityCreated(
                $entiteId,
                1, // fk_type toujours à 1 dans cette méthode
                $postalCode
            );

            return $entiteId;
        } catch (Exception $e) {
            LogService::log('Erreur lors de la vérification/création de l\'entité GeoSector', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'name' => $name,
                'postalCode' => $postalCode
            ]);

            throw $e;
        }
    }

    /**
     * Récupère toutes les entités actives
     * 
     * @return array Liste des entités
     */
    public function getEntites(): void {
        try {
            $stmt = $this->db->prepare('
                SELECT id, encrypted_name, code_postal, ville, fk_type, chk_active, chk_user_delete_pass
                FROM entites
                WHERE chk_active = 1
                ORDER BY code_postal ASC
            ');

            $stmt->execute();
            $entites = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $result = [];
            foreach ($entites as $entite) {
                // Déchiffrement du nom pour chaque entité
                $entite['name'] = ApiService::decryptData($entite['encrypted_name']);
                unset($entite['encrypted_name']);
                $result[] = $entite;
            }

            Response::json([
                'status' => 'success',
                'entites' => $result
            ], 200);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération des entités GeoSector', [
                'level' => 'error',
                'error' => $e->getMessage()
            ]);

            Response::json([
                'status' => 'error',
                'message' => 'Erreur lors de la récupération des entités'
            ], 500);
        }
    }

    /**
     * Recherche les coordonnées GPS d'une caserne de pompiers à partir d'une adresse
     * 
     * @param string $address Adresse complète (adresse + code postal + ville)
     * @param string $postalCode Code postal
     * @param string $city Ville
     * @return array|null Tableau contenant les coordonnées GPS [lat, lng] ou null si non trouvé
     */
    private function findFireStationCoordinates(string $address, string $postalCode, string $city): ?array {
        try {
            // Construire l'adresse complète
            $fullAddress = urlencode($address . ' ' . $postalCode . ' ' . $city);

            // Mots-clés pour rechercher une caserne de pompiers
            $keywords = ['pompiers', 'sapeurs-pompiers', 'sdis', 'caserne', 'centre de secours'];

            foreach ($keywords as $keyword) {
                // Construire l'URL de recherche
                $searchUrl = "https://api-adresse.data.gouv.fr/search/?q=" . urlencode($keyword) . "&postcode=$postalCode&limit=1";

                // Effectuer la requête
                $response = file_get_contents($searchUrl);

                if ($response) {
                    $data = json_decode($response, true);

                    // Vérifier si des résultats ont été trouvés
                    if (isset($data['features']) && count($data['features']) > 0) {
                        $feature = $data['features'][0];

                        // Vérifier si les coordonnées sont disponibles
                        if (isset($feature['geometry']['coordinates'])) {
                            $coordinates = $feature['geometry']['coordinates'];

                            // Les coordonnées sont au format [longitude, latitude]
                            return [
                                'lat' => $coordinates[1],
                                'lng' => $coordinates[0]
                            ];
                        }
                    }
                }
            }

            // Si aucune caserne n'a été trouvée, essayer avec l'adresse de la mairie
            $searchUrl = "https://api-adresse.data.gouv.fr/search/?q=mairie&postcode=$postalCode&limit=1";
            $response = file_get_contents($searchUrl);

            if ($response) {
                $data = json_decode($response, true);

                if (isset($data['features']) && count($data['features']) > 0) {
                    $feature = $data['features'][0];

                    if (isset($feature['geometry']['coordinates'])) {
                        $coordinates = $feature['geometry']['coordinates'];

                        return [
                            'lat' => $coordinates[1],
                            'lng' => $coordinates[0]
                        ];
                    }
                }
            }

            // Si toujours rien, essayer avec l'adresse complète
            $searchUrl = "https://api-adresse.data.gouv.fr/search/?q=$fullAddress&limit=1";
            $response = file_get_contents($searchUrl);

            if ($response) {
                $data = json_decode($response, true);

                if (isset($data['features']) && count($data['features']) > 0) {
                    $feature = $data['features'][0];

                    if (isset($feature['geometry']['coordinates'])) {
                        $coordinates = $feature['geometry']['coordinates'];

                        return [
                            'lat' => $coordinates[1],
                            'lng' => $coordinates[0]
                        ];
                    }
                }
            }

            // Aucune coordonnée trouvée
            return null;
        } catch (Exception $e) {
            LogService::log('Erreur lors de la recherche des coordonnées GPS', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'address' => $address,
                'postalCode' => $postalCode,
                'city' => $city
            ]);

            return null;
        }
    }

    /**
     * Met à jour une entité existante avec les données fournies
     * Seuls les administrateurs (rôle > 2) peuvent modifier certains champs
     * 
     * @param string $id ID de l'entité depuis l'URL
     * @return void
     */
    public function updateEntite(string $id = null): void {
        try {
            // Vérifier l'authentification et les droits d'accès
            $userId = Session::getUserId();
            if (!$userId) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Vous devez être connecté pour effectuer cette action'
                ], 401);
                return;
            }

            // Récupérer le rôle de l'utilisateur
            $stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$user) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Utilisateur non trouvé'
                ], 404);
                return;
            }

            $userRole = (int)$user['fk_role'];
            $isAdmin = $userRole > 1;

            // Récupérer les données de la requête
            $data = Request::getJson();

            // Priorité à l'ID de l'URL, sinon utiliser celui du JSON
            $entiteId = $id ? (int)$id : (isset($data['id']) ? (int)$data['id'] : null);

            if (!$entiteId) {
                Response::json([
                    'status' => 'error',
                    'message' => 'ID de l\'entité requis'
                ], 400);
                return;
            }

            // Récupérer les données actuelles de l'entité pour vérifier si l'adresse a changé
            $stmt = $this->db->prepare('SELECT adresse1, adresse2, code_postal, ville FROM entites WHERE id = ?');
            $stmt->execute([$entiteId]);
            $currentEntite = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$currentEntite) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Entité non trouvée'
                ], 404);
                return;
            }

            // Vérifier si l'adresse a changé
            $addressChanged = false;
            $newAdresse1 = $data['adresse1'] ?? $currentEntite['adresse1'];
            $newAdresse2 = $data['adresse2'] ?? $currentEntite['adresse2'];
            $newCodePostal = $data['code_postal'] ?? $currentEntite['code_postal'];
            $newVille = $data['ville'] ?? $currentEntite['ville'];

            // Vérifier si l'adresse a changé
            if (
                $newAdresse1 !== $currentEntite['adresse1'] ||
                $newAdresse2 !== $currentEntite['adresse2'] ||
                $newCodePostal !== $currentEntite['code_postal'] ||
                $newVille !== $currentEntite['ville']
            ) {
                $addressChanged = true;
            }

            // Si l'adresse a changé, recalculer les coordonnées GPS
            if ($addressChanged) {
                // Construire l'adresse complète
                $fullAddress = $newAdresse1;
                if (!empty($newAdresse2)) {
                    $fullAddress .= ' ' . $newAdresse2;
                }

                // Rechercher les coordonnées GPS de la caserne de pompiers
                $coordinates = $this->findFireStationCoordinates($fullAddress, $newCodePostal, $newVille);

                // Si des coordonnées ont été trouvées, les ajouter aux champs à mettre à jour
                if ($coordinates) {
                    $data['gps_lat'] = $coordinates['lat'];
                    $data['gps_lng'] = $coordinates['lng'];

                    LogService::log('Coordonnées GPS mises à jour suite à un changement d\'adresse', [
                        'level' => 'info',
                        'entiteId' => $entiteId,
                        'lat' => $coordinates['lat'],
                        'lng' => $coordinates['lng']
                    ]);
                }
            }

            // Préparer les champs à mettre à jour
            $updateFields = [];
            $params = [];

            // Champs modifiables par tous les utilisateurs
            if (isset($data['name']) && !empty($data['name'])) {
                $updateFields[] = 'encrypted_name = ?';
                $params[] = ApiService::encryptData($data['name']);
            }

            if (isset($data['adresse1'])) {
                $updateFields[] = 'adresse1 = ?';
                $params[] = $data['adresse1'];
            }

            if (isset($data['adresse2'])) {
                $updateFields[] = 'adresse2 = ?';
                $params[] = $data['adresse2'];
            }

            if (isset($data['code_postal']) && !empty($data['code_postal'])) {
                $updateFields[] = 'code_postal = ?';
                $params[] = $data['code_postal'];
            }

            if (isset($data['ville'])) {
                $updateFields[] = 'ville = ?';
                $params[] = $data['ville'];
            }

            if (isset($data['fk_region'])) {
                $updateFields[] = 'fk_region = ?';
                $params[] = $data['fk_region'];
            }

            if (isset($data['phone'])) {
                $updateFields[] = 'encrypted_phone = ?';
                $params[] = ApiService::encryptData($data['phone']);
            }

            if (isset($data['mobile'])) {
                $updateFields[] = 'encrypted_mobile = ?';
                $params[] = ApiService::encryptData($data['mobile']);
            }

            if (isset($data['email']) && !empty($data['email'])) {
                $updateFields[] = 'encrypted_email = ?';
                $params[] = ApiService::encryptSearchableData($data['email']);
            }

            if (isset($data['chk_copie_mail_recu'])) {
                $updateFields[] = 'chk_copie_mail_recu = ?';
                $params[] = $data['chk_copie_mail_recu'] ? 1 : 0;
            }

            if (isset($data['chk_accept_sms'])) {
                $updateFields[] = 'chk_accept_sms = ?';
                $params[] = $data['chk_accept_sms'] ? 1 : 0;
            }

            // Champs modifiables uniquement par les administrateurs
            if ($isAdmin) {
                if (isset($data['gps_lat'])) {
                    $updateFields[] = 'gps_lat = ?';
                    $params[] = $data['gps_lat'];
                }

                if (isset($data['gps_lng'])) {
                    $updateFields[] = 'gps_lng = ?';
                    $params[] = $data['gps_lng'];
                }

                // Note: stripe_id ne peut plus être modifié ici
                // Les données Stripe sont gérées via la table stripe_accounts

                if (isset($data['chk_demo'])) {
                    $updateFields[] = 'chk_demo = ?';
                    $params[] = $data['chk_demo'] ? 1 : 0;
                }

                if (isset($data['chk_active'])) {
                    $updateFields[] = 'chk_active = ?';
                    $params[] = $data['chk_active'] ? 1 : 0;
                }

                if (isset($data['chk_stripe'])) {
                    $updateFields[] = 'chk_stripe = ?';
                    $params[] = $data['chk_stripe'] ? 1 : 0;
                }
                
                if (isset($data['chk_mdp_manuel'])) {
                    $updateFields[] = 'chk_mdp_manuel = ?';
                    $params[] = $data['chk_mdp_manuel'] ? 1 : 0;
                }
                
                if (isset($data['chk_username_manuel'])) {
                    $updateFields[] = 'chk_username_manuel = ?';
                    $params[] = $data['chk_username_manuel'] ? 1 : 0;
                }
                
                if (isset($data['chk_user_delete_pass'])) {
                    $updateFields[] = 'chk_user_delete_pass = ?';
                    $params[] = $data['chk_user_delete_pass'] ? 1 : 0;
                }

                if (isset($data['chk_lot_actif'])) {
                    $updateFields[] = 'chk_lot_actif = ?';
                    $params[] = $data['chk_lot_actif'] ? 1 : 0;
                }
            }

            // Si aucun champ à mettre à jour, retourner une erreur
            if (empty($updateFields)) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Aucune donnée à mettre à jour'
                ], 400);
                return;
            }

            // Ajouter la date de mise à jour
            $updateFields[] = 'updated_at = NOW()';

            // Construire la requête SQL
            $sql = 'UPDATE entites SET ' . implode(', ', $updateFields) . ' WHERE id = ?';
            $params[] = $entiteId;

            // Exécuter la requête
            $stmt = $this->db->prepare($sql);
            $stmt->execute($params);

            // Vérifier si la mise à jour a réussi
            if ($stmt->rowCount() === 0) {
                Response::json([
                    'status' => 'warning',
                    'message' => 'Aucune modification effectuée'
                ], 200);
                return;
            }

            // Log de mise à jour de l'entité
            $changes = [];
            $encryptedFields = ['name', 'email', 'phone', 'mobile'];

            foreach ($data as $key => $value) {
                if (in_array($key, $encryptedFields)) {
                    // Champs sensibles : booléen uniquement
                    $changes['encrypted_' . $key] = true;
                } else {
                    // Champs non sensibles : valeur
                    $changes[$key] = ['new' => $value];
                }
            }

            if (!empty($changes)) {
                EventLogService::logEntityUpdated((int)$entiteId, $changes);
            }

            Response::json([
                'status' => 'success',
                'message' => 'Entité mise à jour avec succès'
            ], 200);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la mise à jour de l\'entité GeoSector', [
                'level' => 'error',
                'error' => $e->getMessage()
            ]);

            Response::json([
                'status' => 'error',
                'message' => 'Erreur lors de la mise à jour de l\'entité'
            ], 500);
        }
    }

    /**
     * Upload et traite le logo d'une entité
     * Réservé aux administrateurs d'amicale (fk_role == 2)
     * 
     * @param string $id ID de l'entité
     * @return void
     */
    public function uploadLogo(string $id): void {
        try {
            // Vérifier l'authentification
            $userId = Session::getUserId();
            if (!$userId) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Vous devez être connecté pour effectuer cette action'
                ], 401);
                return;
            }

            // Récupérer les infos de l'utilisateur
            $stmt = $this->db->prepare('SELECT fk_role, fk_entite FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$user) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Utilisateur non trouvé'
                ], 404);
                return;
            }

            // Vérifier que l'utilisateur est admin d'amicale (fk_role == 2)
            if ((int)$user['fk_role'] !== 2) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Seuls les administrateurs d\'amicale peuvent uploader un logo'
                ], 403);
                return;
            }

            // Vérifier que l'entité correspond à celle de l'utilisateur
            $entiteId = (int)$id;
            if ($entiteId !== (int)$user['fk_entite']) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Vous ne pouvez modifier que le logo de votre propre amicale'
                ], 403);
                return;
            }

            // Vérifier qu'un fichier a été envoyé
            if (!isset($_FILES['logo']) || $_FILES['logo']['error'] !== UPLOAD_ERR_OK) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Aucun fichier reçu ou erreur lors de l\'upload'
                ], 400);
                return;
            }

            $uploadedFile = $_FILES['logo'];
            
            // Vérifier le type MIME
            $allowedMimes = ['image/jpeg', 'image/jpg', 'image/png'];
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $mimeType = finfo_file($finfo, $uploadedFile['tmp_name']);
            finfo_close($finfo);

            if (!in_array($mimeType, $allowedMimes)) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Format de fichier non autorisé. Seuls PNG, JPG et JPEG sont acceptés'
                ], 400);
                return;
            }

            // Déterminer l'extension
            $extension = match($mimeType) {
                'image/jpeg', 'image/jpg' => 'jpg',
                'image/png' => 'png',
                default => 'jpg'
            };

            // Créer le dossier de destination
            require_once __DIR__ . '/../Services/FileService.php';
            $fileService = new FileService();
            $uploadPath = "/{$entiteId}/logo";
            $fullPath = $fileService->createDirectory($entiteId, $uploadPath);

            // Nom du fichier final
            $fileName = "logo_{$entiteId}_" . time() . ".{$extension}";
            $filePath = $fullPath . '/' . $fileName;

            // Charger l'image avec GD
            $sourceImage = match($mimeType) {
                'image/jpeg', 'image/jpg' => imagecreatefromjpeg($uploadedFile['tmp_name']),
                'image/png' => imagecreatefrompng($uploadedFile['tmp_name']),
                default => false
            };

            if (!$sourceImage) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Impossible de traiter l\'image'
                ], 500);
                return;
            }

            // Obtenir les dimensions originales
            $originalWidth = imagesx($sourceImage);
            $originalHeight = imagesy($sourceImage);

            // Calculer les nouvelles dimensions (max 250px) en gardant le ratio
            $maxSize = 250;
            $ratio = min($maxSize / $originalWidth, $maxSize / $originalHeight, 1);
            $newWidth = (int)($originalWidth * $ratio);
            $newHeight = (int)($originalHeight * $ratio);

            // Créer l'image redimensionnée
            $resizedImage = imagecreatetruecolor($newWidth, $newHeight);
            
            // Préserver la transparence pour les PNG
            if ($mimeType === 'image/png') {
                imagealphablending($resizedImage, false);
                imagesavealpha($resizedImage, true);
                $transparent = imagecolorallocatealpha($resizedImage, 255, 255, 255, 127);
                imagefilledrectangle($resizedImage, 0, 0, $newWidth, $newHeight, $transparent);
            }

            // Redimensionner
            imagecopyresampled(
                $resizedImage, $sourceImage,
                0, 0, 0, 0,
                $newWidth, $newHeight,
                $originalWidth, $originalHeight
            );

            // Sauvegarder l'image (72 DPI est la résolution standard web)
            $saved = match($mimeType) {
                'image/jpeg', 'image/jpg' => imagejpeg($resizedImage, $filePath, 85),
                'image/png' => imagepng($resizedImage, $filePath, 8),
                default => false
            };

            // Libérer la mémoire
            imagedestroy($sourceImage);
            imagedestroy($resizedImage);

            if (!$saved) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Impossible de sauvegarder l\'image'
                ], 500);
                return;
            }

            // Appliquer les permissions
            $fileService->setFilePermissions($filePath);

            // Supprimer l'ancien logo s'il existe
            $stmt = $this->db->prepare('
                SELECT id, file_path FROM medias 
                WHERE support = ? AND support_id = ? AND file_category = ?
            ');
            $stmt->execute(['entite', $entiteId, 'logo']);
            $oldLogo = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($oldLogo && !empty($oldLogo['file_path']) && file_exists($oldLogo['file_path'])) {
                unlink($oldLogo['file_path']);
                // Supprimer l'entrée de la base
                $stmt = $this->db->prepare('DELETE FROM medias WHERE id = ?');
                $stmt->execute([$oldLogo['id']]);
            }

            // Enregistrer dans la table medias
            $stmt = $this->db->prepare('
                INSERT INTO medias (
                    support, support_id, fichier, file_type, file_category,
                    file_size, mime_type, original_name, fk_entite,
                    file_path, original_width, original_height,
                    processed_width, processed_height, is_processed,
                    description, created_at, fk_user_creat
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), ?)
            ');

            $stmt->execute([
                'entite',                          // support
                $entiteId,                         // support_id
                $fileName,                         // fichier
                $extension,                        // file_type
                'logo',                            // file_category
                filesize($filePath),               // file_size
                $mimeType,                         // mime_type
                $uploadedFile['name'],            // original_name
                $entiteId,                         // fk_entite
                $filePath,                         // file_path
                $originalWidth,                    // original_width
                $originalHeight,                   // original_height
                $newWidth,                         // processed_width
                $newHeight,                        // processed_height
                1,                                 // is_processed
                'Logo de l\'entité',              // description
                $userId                            // fk_user_creat
            ]);

            $mediaId = $this->db->lastInsertId();

            LogService::log('Upload de logo réussi', [
                'level' => 'info',
                'userId' => $userId,
                'entiteId' => $entiteId,
                'mediaId' => $mediaId,
                'fileName' => $fileName,
                'originalSize' => "{$originalWidth}x{$originalHeight}",
                'newSize' => "{$newWidth}x{$newHeight}"
            ]);

            Response::json([
                'status' => 'success',
                'message' => 'Logo uploadé avec succès',
                'media_id' => $mediaId,
                'file_name' => $fileName,
                'file_path' => $uploadPath . '/' . $fileName,
                'dimensions' => [
                    'width' => $newWidth,
                    'height' => $newHeight
                ]
            ], 200);

        } catch (Exception $e) {
            LogService::log('Erreur lors de l\'upload du logo', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entiteId' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => 'Erreur lors de l\'upload du logo'
            ], 500);
        }
    }

    /**
     * Récupère le logo d'une entité
     * 
     * @param string $id ID de l'entité
     * @return void
     */
    public function getLogo(string $id): void {
        try {
            // Vérifier l'authentification
            $userId = Session::getUserId();
            if (!$userId) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Vous devez être connecté pour effectuer cette action'
                ], 401);
                return;
            }

            $entiteId = (int)$id;

            // Récupérer le logo depuis la base
            $stmt = $this->db->prepare('
                SELECT id, fichier, file_path, file_type, mime_type, 
                       processed_width, processed_height, file_size
                FROM medias 
                WHERE support = ? AND support_id = ? AND file_category = ?
                ORDER BY created_at DESC
                LIMIT 1
            ');
            $stmt->execute(['entite', $entiteId, 'logo']);
            $logo = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$logo) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Aucun logo trouvé pour cette entité'
                ], 404);
                return;
            }

            if (!file_exists($logo['file_path'])) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Fichier logo introuvable'
                ], 404);
                return;
            }

            // Option 1 : Retourner l'image directement (pour une URL séparée)
            // header('Content-Type: ' . $logo['mime_type']);
            // header('Content-Length: ' . $logo['file_size']);
            // header('Cache-Control: public, max-age=86400'); // Cache 24h
            // readfile($logo['file_path']);
            
            // Option 2 : Retourner en base64 dans JSON (recommandé pour Flutter)
            $imageData = file_get_contents($logo['file_path']);
            if ($imageData === false) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Impossible de lire le fichier logo'
                ], 500);
                return;
            }

            $base64 = base64_encode($imageData);
            $dataUrl = 'data:' . $logo['mime_type'] . ';base64,' . $base64;

            Response::json([
                'status' => 'success',
                'logo' => [
                    'id' => $logo['id'],
                    'data_url' => $dataUrl,
                    'file_name' => $logo['fichier'],
                    'mime_type' => $logo['mime_type'],
                    'width' => $logo['processed_width'],
                    'height' => $logo['processed_height'],
                    'size' => $logo['file_size']
                ]
            ], 200);

        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération du logo', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entiteId' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => 'Erreur lors de la récupération du logo'
            ], 500);
        }
    }
}
