<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Services\StripeService;
use App\Services\LogService;
use App\Services\FileService;
use App\Services\ApiService;
use Session;
use Exception;

/**
 * Controller principal pour les opérations Stripe
 * Gère les comptes Connect, les paiements et Terminal
 */
class StripeController extends Controller {
    private StripeService $stripeService;
    
    public function __construct() {
        parent::__construct();
        $this->stripeService = StripeService::getInstance();
    }
    
    /**
     * POST /api/stripe/accounts
     * Créer un compte Stripe Connect pour une amicale
     */
    public function createAccount(): void {
        try {
            $this->requireAuth();
            
            // Vérifier le rôle de l'utilisateur (comme dans les autres controllers)
            $userId = Session::getUserId();
            $stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $result = $stmt->fetch();
            $userRole = $result ? (int)$result['fk_role'] : 0;
            
            if ($userRole < 2) {
                $this->sendError('Droits insuffisants - Admin amicale minimum requis', 403);
                return;
            }
            
            $data = $this->getJsonInput();
            $entiteId = $data['fk_entite'] ?? Session::getEntityId();
            
            if (!$entiteId) {
                $this->sendError('ID entité requis', 400);
                return;
            }
            
            // Vérifier les droits sur cette entité
            if (Session::getEntityId() != $entiteId && $userRole < 3) {
                $this->sendError('Non autorisé pour cette entité', 403);
                return;
            }
            
            $result = $this->stripeService->createConnectAccount($entiteId);
            
            if ($result['success']) {
                $this->sendSuccess($result);
            } else {
                $this->sendError($result['message'], 400);
            }
            
        } catch (Exception $e) {
            $this->sendError('Erreur lors de la création du compte: ' . $e->getMessage());
        }
    }
    
    /**
     * POST /api/stripe/accounts/{accountId}/onboarding-link
     * Générer un lien d'onboarding pour finaliser la configuration
     */
    public function createOnboardingLink(string $accountId): void {
        try {
            $this->requireAuth();
            
            // Log du début de la requête
            LogService::log('Début createOnboardingLink', [
                'account_id' => $accountId,
                'user_id' => Session::getUserId()
            ]);
            
            // Vérifier le rôle de l'utilisateur
            $userId = Session::getUserId();
            $stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $result = $stmt->fetch();
            $userRole = $result ? (int)$result['fk_role'] : 0;
            
            if ($userRole < 2) {
                $this->sendError('Droits insuffisants', 403);
                return;
            }
            
            $data = $this->getJsonInput();
            $returnUrl = $data['return_url'] ?? '';
            $refreshUrl = $data['refresh_url'] ?? '';
            
            LogService::log('URLs reçues', [
                'return_url' => $returnUrl,
                'refresh_url' => $refreshUrl
            ]);
            
            if (!$returnUrl || !$refreshUrl) {
                $this->sendError('URLs de retour requises', 400);
                return;
            }
            
            $result = $this->stripeService->createOnboardingLink($accountId, $returnUrl, $refreshUrl);
            
            LogService::log('Résultat createOnboardingLink', [
                'success' => $result['success'] ?? false,
                'has_url' => isset($result['url'])
            ]);
            
            if ($result['success']) {
                $this->sendSuccess([
                    'status' => 'success',
                    'url' => $result['url']
                ]);
                exit; // Terminer explicitement après l'envoi de la réponse
            } else {
                $this->sendError($result['message'], 400);
                exit;
            }
            
        } catch (Exception $e) {
            LogService::log('Erreur createOnboardingLink', [
                'level' => 'error',
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            $this->sendError('Erreur: ' . $e->getMessage());
            exit;
        }
    }
    
    /**
     * POST /api/stripe/payments/create-intent
     * Créer une intention de paiement pour Tap to Pay ou paiement Web
     *
     * Payload Tap to Pay:
     * {
     *   "amount": 2500,
     *   "currency": "eur",
     *   "description": "Calendrier pompiers - Passage #789",
     *   "payment_method_types": ["card_present"],
     *   "capture_method": "automatic",
     *   "passage_id": 789,
     *   "amicale_id": 42,
     *   "member_id": 156,
     *   "stripe_account": "acct_1O3ABC456DEF789",
     *   "location_id": "tml_FGH123456789",
     *   "metadata": {...}
     * }
     */
    public function createPaymentIntent(): void {
        try {
            $this->requireAuth();

            $data = $this->getJsonInput();

            // Validation des champs requis
            if (!isset($data['amount']) || !isset($data['passage_id'])) {
                $this->sendError('Montant et passage_id requis', 400);
                return;
            }

            $amount = (int)$data['amount'];
            $passageId = (int)$data['passage_id'];

            // Validation du passage_id (doit être > 0 car le passage est créé avant)
            if ($passageId <= 0) {
                $this->sendError('passage_id invalide. Le passage doit être créé avant le paiement', 400);
                return;
            }

            // Validation du montant
            if ($amount < 100) {
                $this->sendError('Le montant minimum est de 1€ (100 centimes)', 400);
                return;
            }

            if ($amount > 99900) {  // 999€ max selon la doc
                $this->sendError('Le montant maximum est de 999€', 400);
                return;
            }

            // Vérifier que le passage existe et appartient à l'utilisateur
            $stmt = $this->db->prepare('
                SELECT p.*, o.fk_entite, o.id as operation_id
                FROM ope_pass p
                JOIN operations o ON p.fk_operation = o.id
                JOIN ope_users ou ON p.fk_user = ou.id
                WHERE p.id = ? AND ou.fk_user = ?
            ');
            $stmt->execute([$passageId, Session::getUserId()]);
            $passage = $stmt->fetch();

            if (!$passage) {
                $this->sendError('Passage non trouvé ou non autorisé', 404);
                return;
            }

            // Vérifier qu'il n'y a pas déjà un paiement Stripe pour ce passage
            if (!empty($passage['stripe_payment_id'])) {
                $this->sendError('Un paiement Stripe existe déjà pour ce passage', 400);
                return;
            }

            // Vérifier que le montant correspond (passage.montant est en euros, amount en centimes)
            $expectedAmount = (int)round($passage['montant'] * 100);
            if ($amount !== $expectedAmount) {
                $this->sendError("Le montant ne correspond pas au passage (attendu: {$expectedAmount} centimes, reçu: {$amount} centimes)", 400);
                return;
            }

            $entiteId = $passage['fk_entite'];
            $operationId = $passage['operation_id'];
            $fkUser = $passage['fk_user']; // ope_users.id

            // Déterminer le type de paiement (Tap to Pay ou Web)
            $paymentMethodTypes = $data['payment_method_types'] ?? ['card_present'];
            $isTapToPay = in_array('card_present', $paymentMethodTypes);

            // Préparer les paramètres pour StripeService
            $params = [
                'amount' => $amount,
                'currency' => $data['currency'] ?? 'eur',
                'description' => $data['description'] ?? "Calendrier pompiers - Passage #$passageId",
                'payment_method_types' => $paymentMethodTypes,
                'capture_method' => $data['capture_method'] ?? 'automatic',
                'passage_id' => $passageId,
                'fk_entite' => $data['amicale_id'] ?? $entiteId,
                'fk_user' => $data['member_id'] ?? $fkUser,
                'stripe_account' => $data['stripe_account'] ?? null,
                'metadata' => array_merge(
                    [
                        'passage_id' => (string)$passageId,
                        'operation_id' => (string)$operationId,
                        'amicale_id' => (string)($data['amicale_id'] ?? $entiteId),
                        'fk_user' => (string)$fkUser,
                        'created_at' => (string)time(),
                        'type' => $isTapToPay ? 'tap_to_pay' : 'web'
                    ],
                    $data['metadata'] ?? []
                )
            ];

            // Ajouter location_id si fourni (pour Tap to Pay)
            if (isset($data['location_id'])) {
                $params['location_id'] = $data['location_id'];
            }

            // Créer le PaymentIntent via StripeService
            $result = $this->stripeService->createPaymentIntent($params);

            if ($result['success']) {
                // Mettre à jour le passage avec le stripe_payment_id
                $stmt = $this->db->prepare('
                    UPDATE ope_pass
                    SET stripe_payment_id = ?, updated_at = NOW()
                    WHERE id = ?
                ');
                $stmt->execute([$result['payment_intent_id'], $passageId]);

                // Retourner la réponse
                $this->sendSuccess([
                    'client_secret' => $result['client_secret'],
                    'payment_intent_id' => $result['payment_intent_id'],
                    'amount' => $result['amount'],
                    'currency' => $params['currency'],
                    'passage_id' => $passageId,
                    'type' => $isTapToPay ? 'tap_to_pay' : 'web'
                ]);
            } else {
                $this->sendError($result['message'], 400);
            }

        } catch (Exception $e) {
            $this->sendError('Erreur: ' . $e->getMessage());
        }
    }
    
    /**
     * GET /api/stripe/payments/{paymentIntentId}
     * Récupérer le statut d'un paiement depuis ope_pass et Stripe
     */
    public function getPaymentStatus(string $paymentIntentId): void {
        try {
            $this->requireAuth();

            // Récupérer les informations depuis ope_pass
            $stmt = $this->db->prepare("
                SELECT p.*, o.fk_entite,
                       e.encrypted_name as entite_nom,
                       ou.first_name as user_prenom, u.sect_name as user_nom
                FROM ope_pass p
                JOIN operations o ON p.fk_operation = o.id
                LEFT JOIN entites e ON o.fk_entite = e.id
                LEFT JOIN ope_users ou ON p.fk_user = ou.id
                LEFT JOIN users u ON ou.fk_user = u.id
                WHERE p.stripe_payment_id = :pi_id
            ");
            $stmt->execute(['pi_id' => $paymentIntentId]);
            $passage = $stmt->fetch();

            if (!$passage) {
                $this->sendError('Paiement non trouvé', 404);
                return;
            }

            // Vérifier les droits
            $userEntityId = Session::getEntityId();
            $userId = Session::getUserId();

            // Récupérer le rôle depuis la base de données
            $stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $result = $stmt->fetch();
            $userRole = $result ? (int)$result['fk_role'] : 0;

            if ($passage['fk_entite'] != $userEntityId &&
                $passage['fk_user'] != $userId &&
                $userRole < 3) {
                $this->sendError('Non autorisé', 403);
                return;
            }

            // Récupérer le statut en temps réel depuis Stripe
            $stripeStatus = $this->stripeService->getPaymentIntentStatus($paymentIntentId);

            // Déchiffrer le nom de l'entité si nécessaire
            $entiteNom = '';
            if (!empty($passage['entite_nom'])) {
                try {
                    $entiteNom = ApiService::decryptData($passage['entite_nom']);
                } catch (Exception $e) {
                    $entiteNom = 'Entité inconnue';
                }
            }

            $this->sendSuccess([
                'payment_intent_id' => $paymentIntentId,
                'passage_id' => $passage['id'],
                'status' => $stripeStatus['status'] ?? 'unknown',
                'amount' => (int)($passage['montant'] * 100), // montant en BDD est en euros, on convertit en centimes
                'currency' => 'eur',
                'entite' => [
                    'id' => $passage['fk_entite'],
                    'nom' => $entiteNom
                ],
                'user' => [
                    'id' => $passage['fk_user'],
                    'nom' => $passage['user_nom'],
                    'prenom' => $passage['user_prenom']
                ],
                'created_at' => $passage['date_creat'],
                'stripe_details' => $stripeStatus
            ]);
            
        } catch (Exception $e) {
            $this->sendError('Erreur: ' . $e->getMessage());
        }
    }
    
    /**
     * GET /api/stripe/accounts/{entityId}/status
     * Vérifier le statut du compte Stripe d'une entité
     */
    public function getAccountStatus(string $entityId): void {
        try {
            $this->requireAuth();
            
            // Convertir l'entityId en int
            $entityId = (int)$entityId;
            
            // Vérifier les droits : admin de l'amicale ou super admin
            $userEntityId = Session::getEntityId();
            $userId = Session::getUserId();
            
            // Récupérer le rôle depuis la base de données
            $stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $result = $stmt->fetch();
            $userRole = $result ? (int)$result['fk_role'] : 0;
            
            if ($entityId != $userEntityId && $userRole < 3) {
                $this->sendError('Non autorisé', 403);
                return;
            }
            
            // Récupérer le compte Stripe
            $stmt = $this->db->prepare(
                "SELECT sa.*, e.encrypted_name as entite_nom
                 FROM stripe_accounts sa
                 LEFT JOIN entites e ON sa.fk_entite = e.id
                 WHERE sa.fk_entite = :entity_id"
            );
            $stmt->execute(['entity_id' => $entityId]);
            $account = $stmt->fetch();
            
            if (!$account || !$account['stripe_account_id']) {
                $this->sendSuccess([
                    'has_account' => false,
                    'account_id' => null,
                    'location_id' => null,
                    'charges_enabled' => false,
                    'payouts_enabled' => false,
                    'onboarding_completed' => false
                ]);
                return;
            }
            
            // Récupérer le statut depuis Stripe
            $stripeService = StripeService::getInstance();
            $stripeAccount = $stripeService->retrieveAccount($account['stripe_account_id']);
            
            if (!$stripeAccount) {
                $this->sendSuccess([
                    'has_account' => true,
                    'account_id' => $account['stripe_account_id'],
                    'location_id' => $account['stripe_location_id'] ?? null,
                    'charges_enabled' => false,
                    'payouts_enabled' => false,
                    'onboarding_completed' => false,
                    'error' => 'Compte non trouvé sur Stripe'
                ]);
                return;
            }
            
            // Mettre à jour la base de données avec le statut actuel
            $stmt = $this->db->prepare(
                "UPDATE stripe_accounts 
                 SET charges_enabled = :charges,
                     payouts_enabled = :payouts,
                     updated_at = NOW()
                 WHERE id = :id"
            );
            $stmt->execute([
                'charges' => $stripeAccount->charges_enabled ? 1 : 0,
                'payouts' => $stripeAccount->payouts_enabled ? 1 : 0,
                'id' => $account['id']
            ]);
            
            $this->sendSuccess([
                'has_account' => true,
                'account_id' => $account['stripe_account_id'],
                'location_id' => $account['stripe_location_id'] ?? null,
                'charges_enabled' => $stripeAccount->charges_enabled,
                'payouts_enabled' => $stripeAccount->payouts_enabled,
                'onboarding_completed' => $stripeAccount->details_submitted,
                'entite' => [
                    'id' => $entityId,
                    'nom' => $account['entite_nom']
                ]
            ]);
            
        } catch (Exception $e) {
            // Logger::getInstance()->error('Erreur statut compte Stripe', [
            //     'entity_id' => $entityId,
            //     'error' => $e->getMessage()
            // ]);
            $this->sendError('Erreur: ' . $e->getMessage());
        }
    }

    /**
     * GET /api/stripe/config
     * Récupérer la configuration publique Stripe
     */
    public function getPublicConfig(): void {
        try {
            $this->requireAuth();

            $this->sendSuccess([
                'public_key' => $this->stripeService->getPublicKey(),
                'test_mode' => $this->stripeService->isTestMode()
            ]);

        } catch (Exception $e) {
            $this->sendError('Erreur: ' . $e->getMessage());
        }
    }

    /**
     * GET /api/stripe/stats
     * Récupérer les statistiques de paiement
     */
    public function getPaymentStats(): void {
        try {
            $this->requireAuth();
            
            $entiteId = $_GET['fk_entite'] ?? Session::getEntityId();
            $userId = $_GET['fk_user'] ?? null;
            $dateFrom = $_GET['date_from'] ?? date('Y-m-01');
            $dateTo = $_GET['date_to'] ?? date('Y-m-d');
            
            // Vérifier les droits
            // Récupérer le rôle pour vérifier les droits
            $userId = Session::getUserId();
            $stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $result = $stmt->fetch();
            $userRole = $result ? (int)$result['fk_role'] : 0;
            
            if ($entiteId != Session::getEntityId() && $userRole < 3) {
                $this->sendError('Non autorisé', 403);
                return;
            }
            
            $query = "SELECT 
                        COUNT(CASE WHEN status = 'succeeded' THEN 1 END) as total_ventes,
                        SUM(CASE WHEN status = 'succeeded' THEN amount ELSE 0 END) as total_montant,
                        SUM(CASE WHEN status = 'succeeded' THEN application_fee ELSE 0 END) as total_commissions,
                        DATE(created_at) as date_vente
                      FROM stripe_payment_intents
                      WHERE fk_entite = :entite_id
                      AND DATE(created_at) BETWEEN :date_from AND :date_to";
            
            $params = [
                'entite_id' => $entiteId,
                'date_from' => $dateFrom,
                'date_to' => $dateTo
            ];
            
            if ($userId) {
                $query .= " AND fk_user = :user_id";
                $params['user_id'] = $userId;
            }
            
            $query .= " GROUP BY DATE(created_at) ORDER BY date_vente DESC";
            
            $stmt = $this->db->prepare($query);
            $stmt->execute($params);
            $stats = $stmt->fetchAll();
            
            // Calculer les totaux
            $totals = [
                'total_ventes' => 0,
                'total_montant' => 0,
                'total_commissions' => 0
            ];
            
            foreach ($stats as $stat) {
                $totals['total_ventes'] += $stat['total_ventes'];
                $totals['total_montant'] += $stat['total_montant'];
                $totals['total_commissions'] += $stat['total_commissions'];
            }
            
            $this->sendSuccess([
                'stats' => $stats,
                'totals' => $totals,
                'period' => [
                    'from' => $dateFrom,
                    'to' => $dateTo
                ]
            ]);

        } catch (Exception $e) {
            $this->sendError('Erreur: ' . $e->getMessage());
        }
    }

    /**
     * POST /api/stripe/payment-links
     * Créer un Payment Link Stripe pour paiement par QR Code
     *
     * Payload:
     * {
     *   "amount": 2500,
     *   "currency": "eur",
     *   "description": "Calendrier pompiers",
     *   "passage_id": 789,
     *   "metadata": {...}
     * }
     */
    public function createPaymentLink(): void {
        try {
            $this->requireAuth();

            $data = $this->getJsonInput();

            // Validation
            if (!isset($data['amount']) || !isset($data['passage_id'])) {
                $this->sendError('Montant et passage_id requis', 400);
                return;
            }

            $amount = (int)$data['amount'];
            $passageId = (int)$data['passage_id'];

            // Validation du montant (doit être > 0)
            if ($amount <= 0) {
                $this->sendError('Le montant doit être supérieur à 0', 400);
                return;
            }

            // Vérifier que le passage appartient à l'utilisateur ou à son entité
            $userId = Session::getUserId();
            $stmt = $this->db->prepare('
                SELECT p.*, o.fk_entite, ou.fk_user as ope_user_id
                FROM ope_pass p
                JOIN operations o ON p.fk_operation = o.id
                JOIN ope_users ou ON p.fk_user = ou.id
                WHERE p.id = ?
            ');
            $stmt->execute([$passageId]);
            $passage = $stmt->fetch();

            if (!$passage) {
                $this->sendError('Passage non trouvé', 404);
                return;
            }

            // Vérifier les droits : soit l'utilisateur est le créateur du passage, soit il appartient à la même entité
            $userEntityId = Session::getEntityId();
            if ($passage['ope_user_id'] != $userId && $passage['fk_entite'] != $userEntityId) {
                $this->sendError('Passage non autorisé', 403);
                return;
            }

            // Vérifier qu'il n'y a pas déjà un paiement ou un payment link pour ce passage
            if (!empty($passage['stripe_payment_id'])) {
                $this->sendError('Un paiement Stripe existe déjà pour ce passage', 400);
                return;
            }

            if (!empty($passage['stripe_payment_link_id'])) {
                $this->sendError('Un Payment Link existe déjà pour ce passage', 400);
                return;
            }

            // Vérifier que le montant correspond (passage.montant est en euros, amount en centimes)
            $expectedAmount = (int)round($passage['montant'] * 100);
            if ($amount !== $expectedAmount) {
                $this->sendError("Le montant ne correspond pas au passage (attendu: {$expectedAmount} centimes, reçu: {$amount} centimes)", 400);
                return;
            }

            // Préparer les paramètres
            $params = [
                'amount' => $amount,
                'currency' => $data['currency'] ?? 'eur',
                'description' => $data['description'] ?? 'Calendrier pompiers',
                'passage_id' => $passageId,
                'metadata' => $data['metadata'] ?? []
            ];

            // Créer le Payment Link
            $result = $this->stripeService->createPaymentLink($params);

            if ($result['success']) {
                $this->sendSuccess([
                    'payment_link_id' => $result['payment_link_id'],
                    'url' => $result['url'],
                    'amount' => $result['amount'],
                    'passage_id' => $passageId,
                    'type' => 'qr_code'
                ]);
            } else {
                $this->sendError($result['message'], 400);
            }

        } catch (Exception $e) {
            $this->sendError('Erreur: ' . $e->getMessage());
        }
    }

    /**
     * POST /api/stripe/locations
     * Créer une Location Stripe Terminal pour une entité (nécessaire pour Tap to Pay)
     */
    public function createLocation(): void {
        try {
            $this->requireAuth();

            // Vérifier le rôle de l'utilisateur
            $userId = Session::getUserId();
            $stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
            $stmt->execute([$userId]);
            $result = $stmt->fetch();
            $userRole = $result ? (int)$result['fk_role'] : 0;

            if ($userRole < 2) {
                $this->sendError('Droits insuffisants - Admin amicale minimum requis', 403);
                return;
            }

            $data = $this->getJsonInput();
            $entiteId = $data['fk_entite'] ?? Session::getEntityId();

            if (!$entiteId) {
                $this->sendError('ID entité requis', 400);
                return;
            }

            // Vérifier les droits sur cette entité
            if (Session::getEntityId() != $entiteId && $userRole < 3) {
                $this->sendError('Non autorisé pour cette entité', 403);
                return;
            }

            $result = $this->stripeService->createLocation($entiteId);

            if ($result['success']) {
                $this->sendSuccess([
                    'location_id' => $result['location_id'],
                    'message' => $result['message']
                ]);
            } else {
                $this->sendError($result['message'], 400);
            }

        } catch (Exception $e) {
            $this->sendError('Erreur lors de la création de la location: ' . $e->getMessage());
        }
    }

    /**
     * POST /api/stripe/terminal/connection-token
     * Créer un Connection Token pour Stripe Terminal/Tap to Pay
     * Requis par le SDK Stripe Terminal pour se connecter aux readers
     */
    public function createConnectionToken(): void {
        try {
            $this->requireAuth();

            $data = $this->getJsonInput();
            $entiteId = $data['amicale_id'] ?? Session::getEntityId();

            if (!$entiteId) {
                $this->sendError('ID entité requis', 400);
                return;
            }

            // Vérifier les droits sur cette entité
            $userRole = Session::getRole() ?? 0;
            if (Session::getEntityId() != $entiteId && $userRole < 3) {
                $this->sendError('Non autorisé pour cette entité', 403);
                return;
            }

            $result = $this->stripeService->createConnectionToken($entiteId);

            if ($result['success']) {
                $this->sendSuccess([
                    'secret' => $result['secret']
                ]);
            } else {
                $this->sendError($result['message'], 400);
            }

        } catch (Exception $e) {
            $this->sendError('Erreur lors de la création du connection token: ' . $e->getMessage());
        }
    }

    /**
     * POST /api/stripe/payments/cancel
     * Annuler un PaymentIntent Stripe
     *
     * Payload:
     * {
     *   "payment_intent_id": "pi_3SWvho2378xpV4Rn1J43Ks7M"
     * }
     */
    public function cancelPayment(): void {
        try {
            $this->requireAuth();

            $data = $this->getJsonInput();

            // Validation
            if (!isset($data['payment_intent_id'])) {
                $this->sendError('payment_intent_id requis', 400);
                return;
            }

            $paymentIntentId = $data['payment_intent_id'];

            // Vérifier que le passage existe et appartient à l'utilisateur
            $stmt = $this->db->prepare('
                SELECT p.*, o.fk_entite, ou.fk_user as ope_user_id
                FROM ope_pass p
                JOIN operations o ON p.fk_operation = o.id
                JOIN ope_users ou ON p.fk_user = ou.id
                WHERE p.stripe_payment_id = ?
            ');
            $stmt->execute([$paymentIntentId]);
            $passage = $stmt->fetch();

            if (!$passage) {
                $this->sendError('Paiement non trouvé', 404);
                return;
            }

            // Vérifier les droits
            $userId = Session::getUserId();
            $userEntityId = Session::getEntityId();

            if ($passage['ope_user_id'] != $userId && $passage['fk_entite'] != $userEntityId) {
                $this->sendError('Non autorisé', 403);
                return;
            }

            // Annuler le PaymentIntent via StripeService
            $result = $this->stripeService->cancelPaymentIntent($paymentIntentId);

            if ($result['success']) {
                // Retirer le stripe_payment_id du passage
                $stmt = $this->db->prepare('
                    UPDATE ope_pass
                    SET stripe_payment_id = NULL, updated_at = NOW()
                    WHERE id = ?
                ');
                $stmt->execute([$passage['id']]);

                $this->sendSuccess([
                    'status' => 'canceled',
                    'payment_intent_id' => $paymentIntentId,
                    'passage_id' => $passage['id']
                ]);
            } else {
                $this->sendError($result['message'], 400);
            }

        } catch (Exception $e) {
            $this->sendError('Erreur: ' . $e->getMessage());
        }
    }
}