"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOrderReports = exports.getShippingLabel = exports.updateOrderStatus = exports.getAllOrdersAdmin = exports.getUserOrders = exports.createOrder = void 0;
const database_1 = __importDefault(require("../config/database"));
const response_utils_1 = require("../utils/response.utils");
const logger_1 = require("../config/logger");
// 1. Create New Order (Checkout)
const createOrder = async (req, res) => {
    try {
        const userId = req.user?.userId;
        if (!userId)
            return (0, response_utils_1.sendError)(res, 'Unauthorized', null, 401);
        const { shippingAddress, items, paymentMethod = 'CREDIT_CARD', shippingFee = 0, discountAmount = 0, } = req.body;
        if (!items || items.length === 0) {
            return (0, response_utils_1.sendError)(res, 'Order items list cannot be empty', null, 400);
        }
        let addressRecord = await database_1.default.shippingAddress.findFirst({
            where: {
                userId,
                street: shippingAddress.street,
                postalCode: shippingAddress.postalCode,
            },
        });
        if (!addressRecord) {
            addressRecord = await database_1.default.shippingAddress.create({
                data: {
                    userId,
                    fullName: shippingAddress.fullName,
                    street: shippingAddress.street,
                    city: shippingAddress.city,
                    state: shippingAddress.state,
                    postalCode: shippingAddress.postalCode,
                    country: shippingAddress.country || 'India',
                    phone: shippingAddress.phone,
                    isDefault: true,
                },
            });
        }
        const subtotal = items.reduce((sum, item) => {
            const itemPrice = item.discountPrice || item.price;
            return sum + itemPrice * item.quantity;
        }, 0);
        const taxAmount = Math.round((subtotal - discountAmount) * 0.05);
        const grandTotal = Math.max(0, subtotal - discountAmount + shippingFee + taxAmount);
        const orderNumber = `IBW-${Date.now()}-${Math.floor(100 + Math.random() * 900)}`;
        const order = await database_1.default.$transaction(async (tx) => {
            const createdOrder = await tx.order.create({
                data: {
                    orderNumber,
                    userId,
                    shippingAddressId: addressRecord.id,
                    status: 'CONFIRMED',
                    totalAmount: subtotal,
                    discountAmount,
                    shippingFee,
                    grandTotal,
                    items: {
                        create: items.map((item) => ({
                            bookId: item.bookId || item.id,
                            variantId: item.variantId || null,
                            price: item.discountPrice || item.price,
                            quantity: item.quantity,
                            subtotal: (item.discountPrice || item.price) * item.quantity,
                        })),
                    },
                    payment: {
                        create: {
                            userId: userId,
                            gateway: paymentMethod === 'COD' ? 'COD' : 'RAZORPAY',
                            paymentMethod: paymentMethod,
                            status: paymentMethod === 'COD' ? 'PENDING' : 'SUCCESS',
                            gatewayTransactionId: `TXN-${Date.now()}`,
                            amount: grandTotal,
                        },
                    },
                },
                include: {
                    items: { include: { book: true, variant: true } },
                    shippingAddress: true,
                    payment: true,
                },
            });
            // Decrement stock for variants and books
            for (const item of items) {
                const bookId = item.bookId || item.id;
                const qty = Number(item.quantity) || 1;
                if (item.variantId) {
                    await tx.bookVariant.updateMany({
                        where: { id: item.variantId },
                        data: { stock: { decrement: qty } },
                    });
                }
                await tx.book.updateMany({
                    where: { id: bookId },
                    data: { stock: { decrement: qty } },
                });
                await tx.bookInventory.updateMany({
                    where: { bookId },
                    data: { stock: { decrement: qty } },
                });
            }
            return createdOrder;
        });
        // Send Email & SMS Notification stubs
        logger_1.logger.info(`[Notification Engine] Sent Order Confirmation Email to User ${userId} for Order ${orderNumber}`);
        logger_1.logger.info(`[SMS Gateway] Sent Order SMS notification to ${shippingAddress.phone}`);
        return (0, response_utils_1.sendSuccess)(res, 'Order placed successfully!', order, 201);
    }
    catch (error) {
        return (0, response_utils_1.sendError)(res, 'Failed to place order', error.message, 500);
    }
};
exports.createOrder = createOrder;
// 2. Get User Order History
const getUserOrders = async (req, res) => {
    try {
        const userId = req.user?.userId;
        if (!userId)
            return (0, response_utils_1.sendError)(res, 'Unauthorized', null, 401);
        const orders = await database_1.default.order.findMany({
            where: { userId },
            include: {
                items: { include: { book: true } },
                shippingAddress: true,
                payment: true,
            },
            orderBy: { createdAt: 'desc' },
        });
        return (0, response_utils_1.sendSuccess)(res, 'User order history retrieved', orders);
    }
    catch (error) {
        return (0, response_utils_1.sendError)(res, 'Error fetching orders', error.message, 500);
    }
};
exports.getUserOrders = getUserOrders;
// 3. Get All Orders (Admin with Status Filter & Pagination)
const getAllOrdersAdmin = async (req, res) => {
    try {
        const { status, limit = 20, page = 1 } = req.query;
        const take = Number(limit);
        const skip = (Number(page) - 1) * take;
        const where = {};
        if (status)
            where.status = String(status);
        const [orders, total] = await Promise.all([
            database_1.default.order.findMany({
                where,
                take,
                skip,
                include: {
                    user: true,
                    shippingAddress: true,
                    payment: true,
                    items: { include: { book: true } },
                },
                orderBy: { createdAt: 'desc' },
            }),
            database_1.default.order.count({ where }),
        ]);
        return (0, response_utils_1.sendSuccess)(res, 'Admin orders list retrieved', {
            orders,
            pagination: { total, page: Number(page), limit: take, totalPages: Math.ceil(total / take) },
        });
    }
    catch (error) {
        return (0, response_utils_1.sendError)(res, 'Error fetching admin orders', error.message, 500);
    }
};
exports.getAllOrdersAdmin = getAllOrdersAdmin;
// 4. Update Order Status (Admin Workflow: PENDING -> CONFIRMED -> PACKED -> SHIPPED -> DELIVERED / CANCELLED / RETURNED / REFUNDED)
const updateOrderStatus = async (req, res) => {
    try {
        const { id } = req.params;
        const { status, trackingNumber, carrier } = req.body;
        const order = await database_1.default.order.findUnique({
            where: { id },
            include: { user: true, shippingAddress: true },
        });
        if (!order) {
            return (0, response_utils_1.sendError)(res, 'Order not found', null, 404);
        }
        const updatedOrder = await database_1.default.order.update({
            where: { id },
            data: {
                status: status,
            },
            include: { shippingAddress: true, payment: true },
        });
        // Log operational activity event
        await database_1.default.activityLog.create({
            data: {
                adminId: req.user?.adminId,
                action: `ORDER_STATUS_CHANGED_${status}`,
                details: {
                    orderId: id,
                    orderNumber: order.orderNumber,
                    oldStatus: order.status,
                    newStatus: status,
                    trackingNumber,
                    carrier,
                },
            },
        });
        // Trigger Automated Email & SMS Notifications
        logger_1.logger.info(`[Notification Engine] Email notification sent to ${order.user.email} for status update: ${status}`);
        logger_1.logger.info(`[SMS Gateway] SMS dispatch update sent to ${order.shippingAddress.phone}`);
        return (0, response_utils_1.sendSuccess)(res, `Order status updated to '${status}'`, updatedOrder);
    }
    catch (error) {
        return (0, response_utils_1.sendError)(res, 'Error updating order status', error.message, 500);
    }
};
exports.updateOrderStatus = updateOrderStatus;
// 5. Generate Shipping Label HTML / PDF Stub
const getShippingLabel = async (req, res) => {
    try {
        const { id } = req.params;
        const order = await database_1.default.order.findUnique({
            where: { id },
            include: { shippingAddress: true, items: { include: { book: true } } },
        });
        if (!order)
            return (0, response_utils_1.sendError)(res, 'Order not found', null, 404);
        const shippingLabelData = {
            carrier: 'DHL EXPRESS AIRWAYBILL',
            trackingCode: `WAYBILL-${order.orderNumber}`,
            origin: 'Indian Books Worldwide Fulfillment Hub, New Delhi, 110001, India',
            destination: {
                name: order.shippingAddress.fullName,
                street: order.shippingAddress.street,
                city: order.shippingAddress.city,
                state: order.shippingAddress.state,
                zip: order.shippingAddress.postalCode,
                country: order.shippingAddress.country,
                phone: order.shippingAddress.phone,
            },
            packageCount: 1,
            totalWeightKg: 1.4,
            declaredValue: `₹${order.grandTotal}`,
        };
        return (0, response_utils_1.sendSuccess)(res, 'Shipping label generated', shippingLabelData);
    }
    catch (error) {
        return (0, response_utils_1.sendError)(res, 'Shipping label generation failed', error.message, 500);
    }
};
exports.getShippingLabel = getShippingLabel;
// 6. Analytics & Order Performance Reports
const getOrderReports = async (req, res) => {
    try {
        const [statusCounts, totalRevenue] = await Promise.all([
            database_1.default.order.groupBy({
                by: ['status'],
                _count: { status: true },
            }),
            database_1.default.order.aggregate({
                _sum: { grandTotal: true },
                _count: { id: true },
            }),
        ]);
        return (0, response_utils_1.sendSuccess)(res, 'Order analytics report generated', {
            totalOrdersCount: totalRevenue._count.id,
            totalRevenueSum: totalRevenue._sum.grandTotal ? Number(totalRevenue._sum.grandTotal) : 0,
            statusBreakdown: statusCounts,
        });
    }
    catch (error) {
        return (0, response_utils_1.sendError)(res, 'Error generating order report', error.message, 500);
    }
};
exports.getOrderReports = getOrderReports;
//# sourceMappingURL=order.controller.js.map