const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const {
	body,
	validationResult
} = require('express-validator');
const {
	pool
} = require('../db');
const {
	v4: uuidv4
} = require('uuid');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

// Services
const ocrService = require('../services/ocrService');
const taresClassifier = require('../services/taresClassifier');
const edecGenerator = require('../services/edecGenerator');
const exchangeRateService = require('../services/exchangeRateService');
const declarationService = require('../services/declarationService');
const edecSubmissionService = require('../services/edecSubmissionService');

const DOWNLOAD_DIR = path.join(__dirname, '../../edecpdf');
const EXPIRATION_DAYS = 30;

// Configuration Multer
const upload = multer({
	dest: path.join(__dirname, '../../public/uploads'),
	limits: {
		fileSize: 10 * 1024 * 1024
	},
	fileFilter: (req, file, cb) => {
		const allowed = ['image/jpeg', 'image/png', 'application/pdf'];
		if (allowed.includes(file.mimetype)) {
			cb(null, true);
		} else {
			cb(new Error('Formats supportés: JPG, PNG, PDF'));
		}
	}
});

// =========================================================================
// ROUTES PAIEMENT STRIPE CHECKOUT
// =========================================================================

/**
 * ÉTAPE 1 : Préparation de la déclaration (AVANT paiement)
 * - Valide les données
 * - Génère le XML
 * - Crée l'enregistrement DB avec status 'pending_payment'
 * - Retourne le sessionToken pour tracking
 */
router.post('/prepare-declaration', async (req, res) => {
	const { type, vehicle, parties, declaration, declarantType } = req.body;

	if (!type || !vehicle || !parties || !declaration) {
		return res.status(400).json({
			success: false,
			message: 'Données manquantes'
		});
	}

	const txId = uuidv4();
	const conn = await pool.getConnection();

	try {
		await conn.beginTransaction();
		console.log(`[PREPARE-DECLARATION] Début préparation ${type} pour UUID: ${txId}`);

		// Helper pour formater les noms
		const getFullName = (name, firstname, ide) => {
			const isCompany = !!ide && ide.trim() !== 'CHE222251936';
			if (isCompany) return name || '';
			return [firstname, name].filter(p => p && p.trim()).join(' ');
		};

		let data = {};

		if (type === 'import') {
			const imp = parties.importer || {};
			const cons = parties.consignee || {};
			let declarantData = {};
			
			if ((declarantType || 'importer') === 'importer') declarantData = imp;
			else if (declarantType === 'consignee') declarantData = cons;
			else declarantData = parties.declarant || {};

			data = {
				...vehicle,
				...declaration,
				user_name: getFullName(declarantData.name, declarantData.firstname, declarantData.ide),
				user_firstname: declarantData.firstname || null,
				user_address: declarantData.address || null,
				user_zip: declarantData.zip || '',
				user_city: declarantData.city || '',
				user_ide: declarantData.ide || null,
				user_country: 'CH',
				importer_name: getFullName(imp.name, imp.firstname, imp.ide),
				importer_address: imp.address || null,
				importer_zip: imp.zip || '',
				importer_city: imp.city || '',
				importer_ide: imp.ide || null,
				consignee_name: getFullName(cons.name, cons.firstname, cons.ide),
				consignee_address: cons.address || null,
				consignee_zip: cons.zip || '',
				consignee_city: cons.city || '',
				consignee_ide: cons.ide || null,
				language: declaration.language || 'fr'
			};

			// Classification et enrichissement
			const classification = await taresClassifier.classify(data, req.app.appConfigs.taresRules);
			data.commodity_code = data.commodity_code || classification.commodity_code;
			data.statistical_key = data.statistical_key || classification.statistical_key || '911';
			data.origin_country = await taresClassifier.getCountryFromVIN_DB(data.vin) || data.dispatch_country || 'FR';
			data.brand_code = data.brand_code || await declarationService.getBrandCodeByBrandName(data.brand);

			const sum = Number(data.purchase_price || 0) + Number(data.transport_cost || 0) + Number(data.other_costs || 0);
			data.statistical_value_chf = await exchangeRateService.convert(Number(data.purchase_price || 0), data.purchase_currency, 'CHF');
			data.vat_value_chf = await exchangeRateService.convert(sum, data.purchase_currency, 'CHF');

			// Créer la déclaration en DB (sans payment_id pour l'instant)
			const declarationId = await declarationService.createFullImportDeclaration(conn, txId, data, null);
			
			// Générer le XML
			const xml = await edecGenerator.generateImport(data);
			const xmlFilePath = await declarationService.saveXmlFile(conn, txId, xml, declarationId);
			
			// Mettre le status à pending_payment
			await conn.execute(
				`UPDATE declarations SET status = 'pending_payment' WHERE uuid = ?`,
				[txId]
			);

			await conn.commit();

			console.log(`[PREPARE-DECLARATION] ✓ Import préparé: ${txId}`);
			return res.json({
				success: true,
				sessionToken: txId,
				message: 'Déclaration prête pour le paiement'
			});

		} else if (type === 'export') {
			const consignor = parties.consignor || {};
			const consignee = parties.consignee || {};
			let declarantData = {};
			
			if ((declarantType || 'consignor') === 'consignor') declarantData = consignor;
			else if (declarantType === 'consignee') declarantData = consignee;
			else declarantData = parties.declarant || {};

			data = {
				...vehicle,
				...declaration,
				user_name: getFullName(declarantData.name, declarantData.firstname, declarantData.ide),
				user_firstname: declarantData.firstname || null,
				user_address: declarantData.address || null,
				user_zip: declarantData.zip || '',
				user_city: declarantData.city || '',
				user_ide: declarantData.ide || null,
				user_country: 'CH',
				consignor_name: getFullName(consignor.name, consignor.firstname, consignor.ide),
				consignor_address: consignor.address || null,
				consignor_zip: consignor.zip || '',
				consignor_city: consignor.city || '',
				consignor_ide: consignor.ide || null,
				consignee_name: getFullName(consignee.name, consignee.firstname, consignee.ide),
				consignee_address: consignee.address || null,
				consignee_zip: consignee.zip || '',
				consignee_city: consignee.city || '',
				consignee_ide: consignee.ide || null,
				language: declaration.language || 'fr'
			};

			const classification = await taresClassifier.classify(data, req.app.appConfigs.taresRules);
			data.commodity_code = data.commodity_code || classification.commodity_code;
			data.statistical_key = data.statistical_key || classification.statistical_key || '911';
			data.brand_code = data.brand_code || await declarationService.getBrandCodeByBrandName(data.brand);

			const declarationId = await declarationService.createFullExportDeclaration(conn, txId, data, null);
			const xml = await edecGenerator.generateExport(data);
			const xmlFilePath = await declarationService.saveXmlFile(conn, txId, xml, declarationId);
			
			await conn.execute(
				`UPDATE declarations SET status = 'pending_payment' WHERE uuid = ?`,
				[txId]
			);

			await conn.commit();

			console.log(`[PREPARE-DECLARATION] ✓ Export préparé: ${txId}`);
			return res.json({
				success: true,
				sessionToken: txId,
				message: 'Déclaration prête pour le paiement'
			});
		}

		return res.status(400).json({
			success: false,
			message: 'Type de déclaration inconnu'
		});

	} catch (e) {
		await conn.rollback();
		console.error('[PREPARE-DECLARATION] Erreur:', e);
		return res.status(500).json({
			success: false,
			message: e.message
		});
	} finally {
		conn.release();
	}
});

/**
 * ÉTAPE 2 : Vérification du paiement Stripe Checkout (APRÈS retour de Stripe)
 * - Récupère la Checkout Session depuis Stripe
 * - Vérifie que le paiement est bien 'paid'
 * - Met à jour la DB avec le payment_id
 * - Lance la soumission e-dec
 */
router.post('/verify-checkout-session', async (req, res) => {
	const { sessionToken, stripeSessionId } = req.body;

	if (!sessionToken || !stripeSessionId) {
		return res.status(400).json({
			success: false,
			message: 'Paramètres manquants'
		});
	}

	const conn = await pool.getConnection();

	try {
		console.log(`[VERIFY-CHECKOUT] Vérification pour ${sessionToken}, Stripe Session: ${stripeSessionId}`);

		// Vérifier la session Stripe
		const session = await stripe.checkout.sessions.retrieve(stripeSessionId);

		if (session.payment_status !== 'paid') {
			return res.json({
				success: false,
				message: 'Paiement non finalisé',
				paymentStatus: session.payment_status
			});
		}

		console.log(`[VERIFY-CHECKOUT] ✓ Paiement confirmé pour ${sessionToken}`);

		// Vérifier que le sessionToken existe et est en pending_payment
		const [rows] = await conn.execute(
			`SELECT id, xml_file_path FROM declarations WHERE uuid = ? AND status = 'pending_payment'`,
			[sessionToken]
		);

		if (rows.length === 0) {
			return res.status(404).json({
				success: false,
				message: 'Déclaration non trouvée ou déjà traitée'
			});
		}

		const declaration = rows[0];
		const xmlFilePath = declaration.xml_file_path;

		// Mettre à jour avec le payment_id
		await conn.execute(
			`UPDATE declarations SET payment_id = ?, status = 'payment_completed' WHERE uuid = ?`,
			[stripeSessionId, sessionToken]
		);

		console.log(`[VERIFY-CHECKOUT] ✓ DB mise à jour, lancement soumission pour ${sessionToken}`);

		// Lancer la soumission e-dec en arrière-plan
		setTimeout(() => {
			edecSubmissionService.submitDeclaration(xmlFilePath, sessionToken).catch(err => {
				console.error(`[SUBMISSION-BACKGROUND] Erreur fatale pour ${sessionToken}:`, err);
			});
		}, 100);

		return res.json({
			success: true,
			sessionToken: sessionToken,
			message: 'Paiement validé, soumission démarrée'
		});

	} catch (error) {
		console.error('[VERIFY-CHECKOUT] Erreur:', error);
		return res.status(500).json({
			success: false,
			message: 'Erreur lors de la vérification du paiement'
		});
	} finally {
		conn.release();
	}
});

// =========================================================================
// ROUTES DE SERVICE (INCHANGÉES)
// =========================================================================
router.get('/health', (req, res) => {
	res.json({
		status: 'OK',
		timestamp: new Date().toISOString(),
		service: 'e-dec Node.js Backend',
		version: '1.4.0'
	});
});

router.get('/countries', (req, res) => res.json(req.app.appConfigs.countries || {}));
router.get('/currencies', (req, res) => res.json(req.app.appConfigs.currencies || {}));

router.get('/exchange-rates', async (req, res) => {
	try {
		const rates = await exchangeRateService.getCurrentRates();
		res.json(rates);
	} catch (e) {
		res.status(500).json({
			error: e.message
		});
	}
});

router.post('/convert-currency', [
	body('amount').isFloat({
		min: 0
	}),
	body('from').isString().isLength({
		min: 3,
		max: 3
	}),
	body('to').optional().isString().isLength({
		min: 3,
		max: 3
	})
], async (req, res) => {
	const errors = validationResult(req);
	if (!errors.isEmpty()) {
		return res.status(400).json({
			error: 'Paramètres invalides',
			details: errors.array()
		});
	}
	try {
		const {
			amount,
			from,
			to = 'CHF'
		} = req.body;
		const converted = await exchangeRateService.convert(Number(amount), from, to);
		res.json({
			converted
		});
	} catch (e) {
		res.status(500).json({
			error: e.message
		});
	}
});

// =========================================================================
// ROUTES MÉTIER (INCHANGÉES)
// =========================================================================
router.post('/ocr', upload.single('registration_card'), async (req, res) => {
    const filePath = req.file?.path;
    if (!filePath) {
        return res.status(400).json({ error: 'Aucun fichier fourni' });
    }

    try {
        // Récupération du contexte envoyé depuis le frontend (import/export)
        const context = req.body.context || 'import';

        // Passage du contexte au service OCR
        const extractedData = await ocrService.extractFromFile(filePath, req.file.mimetype, context);
        res.json(extractedData);
    } catch (error) {
        console.error('Erreur OCR complète:', error);
        res.status(500).json({
            error: 'Erreur OCR',
            details: error.message,
            hint: 'Vérifiez que votre clé API OpenRouter est valide et que le fichier est lisible.'
        });
    } finally {
        if (filePath && fs.existsSync(filePath)) {
            try {
                fs.unlinkSync(filePath);
            } catch (_) {}
        }
    }
});


router.post('/validate-vin', [
	body('vin').isString().isLength({
		min: 17,
		max: 17
	})
], async (req, res) => {
	const {
		vin
	} = req.body;
	const valid = /^[A-HJ-NPR-Z0-9]{17}$/.test((vin || '').toUpperCase());
	let country = null;
	try {
		if (valid) {
			country = await taresClassifier.getCountryFromVIN_DB(vin);
		}
		res.json({
			valid,
			country
		});
	} catch (e) {
		res.status(500).json({
			error: e.message
		});
	}
});

router.post('/classify-vehicle', async (req, res) => {
	try {
		const classification = await taresClassifier.classify(req.body, req.app.appConfigs.taresRules);
		res.json(classification);
	} catch (error) {
		console.error('Erreur classification:', error);
		res.status(500).json({
			error: error.message
		});
	}
});

router.post('/brand-codes/lookup', [
	body('brand').trim().notEmpty().withMessage("Le nom de la marque est requis.")
], async (req, res) => {
	const errors = validationResult(req);
	if (!errors.isEmpty()) {
		return res.status(400).json({
			error: 'Champs invalides',
			details: errors.array()
		});
	}
	try {
		const {
			brand
		} = req.body;
		const brandCode = await declarationService.getBrandCodeByBrandName(brand);
		if (brandCode) {
			return res.json({
				brandCode
			});
		}
		const options = await declarationService.getAllBrandCodes();
		if (options.length === 0) {
			return res.status(404).json({
				message: "Liste des codes de marque non disponible."
			});
		}
		return res.json({
			options
		});
	} catch (error) {
		console.error('Erreur lors de la recherche du code de marque:', error);
		return res.status(500).json({
			error: "Erreur interne du serveur lors de la recherche."
		});
	}
});

// =========================================================================
// SUIVI ET TÉLÉCHARGEMENT (INCHANGÉS)
// =========================================================================
router.get('/submission-status-sse/:sessionToken', async (req, res) => {
	const {
		sessionToken
	} = req.params;
	console.log(`[SSE] Nouvelle connexion pour ${sessionToken}`);

	res.setHeader('Content-Type', 'text/event-stream');
	res.setHeader('Cache-Control', 'no-cache');
	res.setHeader('Connection', 'keep-alive');
	res.setHeader('Access-Control-Allow-Origin', '*');

	const sendStatusUpdate = (data) => {
		try {
			if (res.finished) return;
			res.write(`data: ${JSON.stringify(data)}\n\n`);
			if (data.status === 'submitted' || data.status === 'submission_error') {
				setTimeout(() => {
					if (!res.finished) res.end();
				}, 100);
			}
		} catch (error) {
			console.error(`[SSE] Erreur envoi données pour ${sessionToken}:`, error);
		}
	};

	edecSubmissionService.registerListener(sessionToken, sendStatusUpdate);

	try {
		const [rows] = await pool.execute(`
        SELECT status, declaration_number, liste_importation_path, bulletin_delivrance_path,
               COALESCE(error_message, '') as error_message, submission_date
        FROM declarations WHERE uuid = ?`, [sessionToken]);

		if (rows.length > 0) {
			const declaration = rows[0];
			const {
				progress,
				step
			} = declarationService.getSubmissionProgress(declaration.status);

			sendStatusUpdate({
				status: declaration.status,
				progress,
				step,
				declarationNumber: declaration.declaration_number,
				listePath: declaration.liste_importation_path,
				bulletinPath: declaration.bulletin_delivrance_path,
				submissionDate: declaration.submission_date,
				error: declaration.error_message
			});
		}
	} catch (error) {
		console.error(`[SSE] Erreur vérification état initial ${sessionToken}:`, error);
	}

	const cleanup = () => {
		if (!res.finished) {
			console.log(`[SSE] Connexion fermée pour ${sessionToken} - Nettoyage`);
			edecSubmissionService.removeListener(sessionToken);
			res.end();
		}
	};

	req.on('close', cleanup);
	req.on('error', cleanup);
});

router.get('/submission-status/:sessionToken', async (req, res) => {
	const {
		sessionToken
	} = req.params;
	try {
		const [rows] = await pool.execute(
			`SELECT status, 
            declaration_number, 
            liste_importation_path, 
            bulletin_delivrance_path, 
            COALESCE(error_message, '') as error_message, 
            submission_date
     FROM declarations
     WHERE uuid = ?`,
			[sessionToken]
		);
		if (rows.length === 0) {
			return res.status(404).json({
				error: 'Session non trouvée'
			});
		}
		const declaration = rows[0];
		const {
			progress,
			step
		} = declarationService.getSubmissionProgress(declaration.status);

		res.json({
			status: declaration.status,
			progress,
			step,
			declarationNumber: declaration.declaration_number,
			listePath: declaration.liste_importation_path,
			bulletinPath: declaration.bulletin_delivrance_path,
			submissionDate: declaration.submission_date,
			error: declaration.error_message
		});
	} catch (error) {
		console.error('[SUBMISSION-STATUS] Erreur:', error);
		res.status(500).json({
			error: 'Erreur serveur'
		});
	}
});

router.get('/download-pdf', async (req, res) => {
	const rawFilePath = req.query.path;
	if (!rawFilePath) {
		return res.status(400).json({
			error: 'Paramètre de chemin manquant'
		});
	}
	const safeFilePath = path.resolve(rawFilePath);
	if (!safeFilePath.startsWith(DOWNLOAD_DIR)) {
		console.warn(`[DOWNLOAD-SECURITY] Tentative d'accès illégal : ${rawFilePath}`);
		return res.status(403).json({
			error: 'Accès refusé. Chemin non autorisé.'
		});
	}

	if (!fs.existsSync(safeFilePath)) {
		return res.status(404).json({
			error: 'Fichier non trouvé sur le serveur'
		});
	}

	const sessionToken = path.basename(safeFilePath).split('_')[0];
	try {
		const [rows] = await pool.execute(
			`SELECT submission_date FROM declarations WHERE uuid = ? AND status = 'submitted'`,
			[sessionToken]
		);
		if (rows.length === 0 || !rows[0].submission_date) {
			return res.status(404).json({
				error: 'Déclaration non trouvée ou non finalisée.'
			});
		}

		const submissionDate = new Date(rows[0].submission_date);
		const expirationDate = new Date(submissionDate.getTime() + EXPIRATION_DAYS * 24 * 60 * 60 * 1000);

		if (new Date() > expirationDate) {
			return res.status(410).json({
				error: `Le lien de téléchargement a expiré (limite de ${EXPIRATION_DAYS} jours).`
			});
		}

		res.setHeader('Content-Type', 'application/pdf');
		res.setHeader('Content-Disposition', `attachment; filename="${path.basename(safeFilePath)}"`);
		fs.createReadStream(safeFilePath).pipe(res);

	} catch (error) {
		console.error('[DOWNLOAD-PDF] Erreur:', error);
		res.status(500).json({
			error: 'Erreur serveur.'
		});
	}
});

router.post('/submission-error/report', async (req, res) => {
	const { sessionToken, email } = req.body;

	// Validation simple
	if (!sessionToken || !email) {
		return res.status(400).json({
			success: false,
			error: 'Session token et email requis'
		});
	}

	// Validation format email
	const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
	if (!emailRegex.test(email)) {
		return res.status(400).json({
			success: false,
			error: 'Format d\'email invalide'
		});
	}

	try {
		// Mise à jour de l'email dans la table declarations
		const [result] = await pool.execute(
			`UPDATE declarations SET user_email = ? WHERE uuid = ? AND status = 'submission_error'`,
			[email, sessionToken]
		);

		if (result.affectedRows === 0) {
			return res.status(404).json({
				success: false,
				error: 'Déclaration non trouvée ou statut incorrect'
			});
		}

		console.log(`[ERROR-REPORT] Email ${email} enregistré pour la session ${sessionToken}`);
		
		res.json({
			success: true,
			message: 'Votre email a été enregistré. Notre équipe vous contactera.'
		});
	} catch (error) {
		console.error('[ERROR-REPORT] Erreur:', error);
		res.status(500).json({
			success: false,
			error: 'Erreur lors de l\'enregistrement de l\'email.'
		});
	}
});

module.exports = router;