const express = require('express');
const router = express.Router();
const Order = require('../models/Order');
const Cart = require('../models/Cart');
const Product = require('../models/Product');
const Coupon = require('../models/Coupon');
const { protect, authorize } = require('../middleware/auth');
const { v4: uuidv4 } = require('uuid');

// Generate unique order number
const generateOrderNumber = () => {
    const timestamp = Date.now().toString().slice(-8);
    const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
    return `ORD-${timestamp}-${random}`;
};

// @desc    Create new order
// @route   POST /api/orders
// @access  Private
router.post('/', protect, async (req, res) => {
    try {
        const { shippingAddress, paymentMethod, couponCode, shippingCost } = req.body;

        // Get user's cart
        const cart = await Cart.findOne({ user: req.user.id }).populate('items.product');
        if (!cart || cart.items.length === 0) {
            return res.status(400).json({
                success: false,
                error: 'Cart is empty'
            });
        }

        // Create order items from cart items
        const orderItems = cart.items.map(item => ({
            product: item.product._id,
            quantity: item.quantity,
            size: item.size,
            color: item.color,
            price: item.product.price
        }));

        // Calculate subtotal
        const subtotal = orderItems.reduce(
            (total, item) => total + item.price * item.quantity,
            0
        );

        let discount = 0;
        let validCouponCode = null;

        // Validate and apply coupon if provided
        if (couponCode) {
            const coupon = await Coupon.findOne({ code: couponCode.toUpperCase() });
            if (coupon) {
                const validation = coupon.isValid(subtotal);
                if (validation.valid) {
                    discount = coupon.calculateDiscount(subtotal);
                    validCouponCode = coupon.code;
                    // Increment usage count
                    coupon.usedCount += 1;
                    await coupon.save();
                }
            }
        }

        // Calculate total
        const totalPrice = subtotal - discount + (shippingCost || 0);

        // Generate order number
        const orderNumber = generateOrderNumber();

        // Create order
        const order = await Order.create({
            orderNumber,
            user: req.user.id,
            items: orderItems,
            shippingAddress,
            paymentMethod,
            subtotal,
            shippingCost: shippingCost || 0,
            discount,
            couponCode: validCouponCode,
            totalPrice,
            statusHistory: [{
                status: 'pending',
                timestamp: new Date(),
                note: 'Order placed'
            }]
        });

        // Clear cart
        cart.items = [];
        await cart.save();

        // Populate order details
        const populatedOrder = await Order.findById(order._id)
            .populate('items.product')
            .populate('user', 'name email');

        res.status(201).json({
            success: true,
            data: populatedOrder
        });
    } catch (err) {
        console.error('Order creation error:', err);
        res.status(400).json({
            success: false,
            error: err.message
        });
    }
});

// @desc    Get all orders
// @route   GET /api/orders
// @access  Private/Admin
router.get('/', protect, authorize('admin'), async (req, res) => {
    try {
        const orders = await Order.find()
            .populate('user', 'name email')
            .populate('items.product')
            .sort({ createdAt: -1 });

        res.status(200).json({
            success: true,
            count: orders.length,
            data: orders
        });
    } catch (err) {
        res.status(400).json({
            success: false,
            error: err.message
        });
    }
});

// @desc    Get user's orders
// @route   GET /api/orders/myorders
// @access  Private
router.get('/myorders', protect, async (req, res) => {
    try {
        const orders = await Order.find({ user: req.user.id })
            .populate('items.product')
            .sort({ createdAt: -1 });

        res.status(200).json({
            success: true,
            count: orders.length,
            data: orders
        });
    } catch (err) {
        res.status(400).json({
            success: false,
            error: err.message
        });
    }
});

// @desc    Get single order
// @route   GET /api/orders/:id
// @access  Private
router.get('/:id', protect, async (req, res) => {
    try {
        const order = await Order.findById(req.params.id)
            .populate('user', 'name email')
            .populate('items.product');

        if (!order) {
            return res.status(404).json({
                success: false,
                error: 'Order not found'
            });
        }

        // Check if user is admin or order owner
        if (order.user._id.toString() !== req.user.id && req.user.role !== 'admin') {
            return res.status(403).json({
                success: false,
                error: 'Not authorized to access this order'
            });
        }

        res.status(200).json({
            success: true,
            data: order
        });
    } catch (err) {
        res.status(400).json({
            success: false,
            error: err.message
        });
    }
});

// @desc    Track order by order number
// @route   GET /api/orders/track/:orderNumber
// @access  Public
router.get('/track/:orderNumber', async (req, res) => {
    try {
        const order = await Order.findOne({ orderNumber: req.params.orderNumber })
            .populate('items.product', 'name thumbImage')
            .select('-user');

        if (!order) {
            return res.status(404).json({
                success: false,
                error: 'Order not found'
            });
        }

        res.status(200).json({
            success: true,
            data: order
        });
    } catch (err) {
        res.status(400).json({
            success: false,
            error: err.message
        });
    }
});

// @desc    Update order status
// @route   PUT /api/orders/:id/status
// @access  Private/Admin
router.put('/:id/status', protect, authorize('admin'), async (req, res) => {
    try {
        const { status, note, trackingNumber } = req.body;
        const order = await Order.findById(req.params.id);

        if (!order) {
            return res.status(404).json({
                success: false,
                error: 'Order not found'
            });
        }

        order.status = status;

        // Add to status history
        order.statusHistory.push({
            status,
            timestamp: new Date(),
            note: note || `Order status updated to ${status}`
        });

        if (status === 'delivered') {
            order.isDelivered = true;
            order.deliveredAt = Date.now();
        }

        if (trackingNumber) {
            order.trackingNumber = trackingNumber;
        }

        await order.save();

        res.status(200).json({
            success: true,
            data: order
        });
    } catch (err) {
        res.status(400).json({
            success: false,
            error: err.message
        });
    }
});

// @desc    Update order payment status
// @route   PUT /api/orders/:id/pay
// @access  Private
router.put('/:id/pay', protect, async (req, res) => {
    try {
        const { paymentResult } = req.body;
        const order = await Order.findById(req.params.id);

        if (!order) {
            return res.status(404).json({
                success: false,
                error: 'Order not found'
            });
        }

        // Check if user is admin or order owner
        if (order.user.toString() !== req.user.id && req.user.role !== 'admin') {
            return res.status(403).json({
                success: false,
                error: 'Not authorized to update this order'
            });
        }

        order.isPaid = true;
        order.paidAt = Date.now();
        order.paymentResult = paymentResult;
        order.status = 'processing';

        // Add to status history
        order.statusHistory.push({
            status: 'processing',
            timestamp: new Date(),
            note: 'Payment received, order is being processed'
        });

        await order.save();

        res.status(200).json({
            success: true,
            data: order
        });
    } catch (err) {
        res.status(400).json({
            success: false,
            error: err.message
        });
    }
});

module.exports = router;