const express = require('express');
const router = express.Router();
const Tour = require('../models/Tour');
const Scene = require('../models/Scene');
const { protect, optionalAuth } = require('../middlewares/authMiddleware');
const { propagateScenePrivacy } = require('../utils/sceneHelper');
const crypto = require('crypto');

// @route   POST /api/tours
// @desc    Tạo một Tour mới (bước đầu tiên trước khi upload ảnh)
// @access  Private
router.post('/', protect, async (req, res) => {
    try {
        const { name, description, lat, lng, privacy } = req.body;

        if (!name) {
            return res.status(400).json({ message: 'Tên Tour là bắt buộc.' });
        }

        const newTour = new Tour({
            name,
            description,
            location: { lat: Number(lat) || 0, lng: Number(lng) || 0 },
            createdBy: req.user._id,
            privacy: privacy || 'private',
            scenes: [],
            shareToken: (privacy === 'shared') ? crypto.randomBytes(24).toString('hex') : undefined
        });

        if (newTour.privacy === 'shared') {
            // Thiết lập hạn mặc định 7 ngày nếu không chỉ định
            const expires = new Date();
            expires.setDate(expires.getDate() + 7);
            newTour.shareTokenExpires = expires;
        }

        await newTour.save();
        res.status(201).json({ message: 'Tour đã được tạo thành công.', tour: newTour });
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

// @route   PUT /api/tours/:id
// @desc    Cập nhật Tour và lan truyền quyền riêng tư xuống các cảnh con
// @access  Private (Chủ sở hữu hoặc Admin)
router.put('/:id', protect, async (req, res) => {
    try {
        const { 
            name, 
            description, 
            lat, 
            lng, 
            privacy, 
            sharedWithUsers, 
            sharedEmails, 
            shareExpireDays 
        } = req.body;

        const tour = await Tour.findById(req.params.id);
        if (!tour) return res.status(404).json({ message: 'Tour không tồn tại.' });

        if (tour.createdBy.toString() !== req.user._id.toString() && req.user.role !== 'admin') {
            return res.status(403).json({ message: 'Bạn không có quyền chỉnh sửa Tour này.' });
        }

        tour.name = name || tour.name;
        tour.description = description !== undefined ? description : tour.description;
        if (lat !== undefined) tour.location.lat = Number(lat);
        if (lng !== undefined) tour.location.lng = Number(lng);

        if (privacy) tour.privacy = privacy;

        // Xử lý logic Token cho chế độ 'shared' (Link-based)
        if (tour.privacy === 'shared') {
            if (!tour.shareToken) tour.shareToken = crypto.randomBytes(24).toString('hex');
            if (shareExpireDays && shareExpireDays !== 'never') {
                const expires = new Date();
                expires.setDate(expires.getDate() + parseInt(shareExpireDays));
                tour.shareTokenExpires = expires;
            } else if (shareExpireDays === 'never') {
                tour.shareTokenExpires = null;
            }
        } else {
            tour.shareToken = undefined;
            tour.shareTokenExpires = undefined;
        }

        // Cập nhật danh sách thành viên được chia sẻ
        if (tour.privacy === 'member' || tour.privacy === 'shared') {
            if (sharedWithUsers) {
                try { tour.sharedWith = JSON.parse(sharedWithUsers); } catch (e) { }
            }
            if (sharedEmails) {
                try { tour.sharedEmails = JSON.parse(sharedEmails); } catch (e) { }
            }
        } else if (tour.privacy === 'private') {
            tour.sharedWith = [];
            tour.sharedEmails = [];
        }

        await tour.save();

        // [CORE LOGIC] Lan truyền thiết lập mới xuống toàn bộ các Scene con trong Tour
        await propagateScenePrivacy(tour._id, {
            privacy: tour.privacy,
            shareToken: tour.shareToken,
            shareTokenExpires: tour.shareTokenExpires,
            sharedWith: tour.sharedWith,
            sharedEmails: tour.sharedEmails
        }, req.user._id);

        res.json({ message: 'Tour đã được cập nhật thành công.', tour });
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

// @route   GET /api/tours/:id
// @desc    Lấy chi tiết Tour và danh sách các cảnh (Kiểm tra quyền truy cập)
// @access  Public (Xác thực thông qua Privacy/Token)
router.get('/:id', optionalAuth, async (req, res) => {
    try {
        const tour = await Tour.findById(req.params.id)
            .populate('createdBy', 'username')
            .populate({
                path: 'rootSceneId',
                select: 'assetId', // Chỉ lấy assetId của rootScene
                populate: { path: 'assetId', select: '_id' } // Populate assetId để lấy _id của Asset
            })
            .populate({
                path: 'scenes',
                select: 'name description assetId gps status privacy shareToken shareTokenExpires sharedWith sharedEmails createdBy',
                populate: { path: 'assetId', select: '_id' }
            })
            .lean();

        if (!tour) return res.status(404).json({ message: 'Tour không tồn tại.' });

        const tourCreatedById = tour.createdBy?._id || tour.createdBy;
        const isOwner = req.user && req.user._id && tourCreatedById && tourCreatedById.toString() === req.user._id.toString();
        const isAdmin = req.user && req.user.role === 'admin';
        const isTokenValid = tour.shareToken && (!tour.shareTokenExpires || new Date() < tour.shareTokenExpires);
        const userEmail = req.user ? req.user.email : null;
        const token = req.query.token;
        
        // [Security] Check permissions based on tour privacy
        let hasAccess = tour.privacy === 'public' || isOwner || isAdmin;
        
        // Shared link access - check token validity
        if (!hasAccess && tour.privacy === 'shared' && token && isTokenValid) {
            hasAccess = token === tour.shareToken;
        }
        
        // Member access - check if user is in sharedWith or sharedEmails
        if (!hasAccess && tour.privacy === 'member' && req.user && req.user._id && req.user.role !== 'guest') {
            hasAccess = true;
        }
        
        // Fallback for specific shared members
        if (!hasAccess && tour.privacy === 'member' && req.user && req.user._id) {
            hasAccess = tour.sharedWith.some(u => u.toString() === req.user._id.toString()) || 
                        (userEmail && tour.sharedEmails.some(email => email.toLowerCase() === userEmail.toLowerCase()));
        }
        
        // Private tours - only owner and admin
        // (hasAccess already set above if owner/admin)

        if (!hasAccess) return res.status(403).json({ message: 'Bạn không có quyền truy cập Tour này.' });

        res.json(tour);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

// @route   GET /api/tours
// @desc    Lấy danh sách Tour công khai, member, shared (với token), hoặc của chính mình
// @access  Public/Private
router.get('/', optionalAuth, async (req, res) => {
    try {
        const { token } = req.query;
        let query = { privacy: 'public' };

        if (req.user && req.user.role !== 'guest') {
            query = {
                $or: [
                    { privacy: 'public' },
                    { privacy: 'member' },
                    { createdBy: req.user._id },
                    { privacy: 'member', sharedWith: req.user._id },
                    { privacy: 'member', sharedEmails: req.user.email }
                ]
            };
        }

        // [Task 4.1] Support shared tours via token for guests
        if (token) {
            const tourWithToken = await Tour.findOne({
                shareToken: token,
                privacy: 'shared',
                $or: [{ shareTokenExpires: null }, { shareTokenExpires: { $gt: new Date() } }]
            }).select('_id');
            
            if (tourWithToken) {
                query = {
                    $or: [
                        query,
                        { _id: tourWithToken._id }
                    ]
                };
            }
        }

        const tours = await Tour.find(query)
            .populate('createdBy', 'username')
            .populate({
                path: 'rootSceneId',
                select: 'assetId', // Chỉ lấy assetId của rootScene
                populate: { path: 'assetId', select: '_id' } // Populate assetId để lấy _id của Asset
            })
            .sort({ createdAt: -1 })
            .lean();

        res.json(tours);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

// @route   DELETE /api/tours/:id
// @desc    Xóa Tour và xóa dây chuyền toàn bộ Scene/Asset bên trong
// @access  Private (Chủ sở hữu hoặc Admin)
router.delete('/:id', protect, async (req, res) => {
    try {
        const tour = await Tour.findById(req.params.id);
        if (!tour) return res.status(404).json({ message: 'Tour không tồn tại.' });

        if (tour.createdBy.toString() !== req.user._id.toString() && req.user.role !== 'admin') {
            return res.status(403).json({ message: 'Bạn không có quyền xóa Tour này.' });
        }

        const { deleteSceneCascade } = require('../utils/sceneHelper');
        const scenesInTour = await Scene.find({ tourId: tour._id });
        
        for (const scene of scenesInTour) {
            await deleteSceneCascade(scene._id, req.user._id);
        }

        await Tour.findByIdAndDelete(req.params.id);
        res.json({ message: `Tour "${tour.name}" đã được xóa thành công.` });
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

/**
 * Tính toán và cập nhật tọa độ trung tâm (location) của Tour 
 * dựa trên giá trị trung bình tọa độ GPS của tất cả các cảnh con hiện có.
 * @param {string} tourId - ID của Tour cần cập nhật
 */
const updateTourCenter = async (tourId) => {
    try {
        const scenes = await Scene.find({ tourId }).select('gps');
        
        if (!scenes || scenes.length === 0) return;

        let totalLat = 0;
        let totalLng = 0;
        let validCount = 0;

        scenes.forEach(scene => {
            // Chỉ tính toán dựa trên các cảnh có tọa độ GPS hợp lệ (khác 0,0)
            if (scene.gps && 
                typeof scene.gps.lat === 'number' && 
                typeof scene.gps.lng === 'number' &&
                (scene.gps.lat !== 0 || scene.gps.lng !== 0)) {
                
                totalLat += scene.gps.lat;
                totalLng += scene.gps.lng;
                validCount++;
            }
        });

        if (validCount > 0) {
            await Tour.findByIdAndUpdate(tourId, {
                location: {
                    lat: totalLat / validCount,
                    lng: totalLng / validCount
                }
            }, { 
                // Thay thế cho 'new: true' để lấy dữ liệu sau khi cập nhật
                returnDocument: 'after' 
            });
        }
    } catch (error) {
        console.error(`[TourController] Error updating center for tour ${tourId}:`, error.message);
    }
};

// @route   POST /api/tours/recalculate-all
// @desc    Admin: Tính toán lại trung tâm cho toàn bộ Tour trong hệ thống
// @access  Private (Admin only)
router.post('/recalculate-all', protect, async (req, res) => {
    if (req.user.role !== 'admin') {
        return res.status(403).json({ message: 'Tính năng này chỉ dành cho Quản trị viên.' });
    }

    try {
        const tours = await Tour.find({});
        let processedCount = 0;

        // Thực hiện tuần tự để tránh gây áp lực quá lớn lên cơ sở dữ liệu
        for (const tour of tours) {
            await updateTourCenter(tour._id);
            processedCount++;
        }

        res.json({ 
            message: `Đã hoàn thành tính toán lại trung tâm cho ${processedCount} Tour.`,
            processedCount 
        });
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

router.updateTourCenter = updateTourCenter;
module.exports = router;