import { Request, Response } from 'express';
import prisma from '../config/database';
import { sendSuccess, sendError } from '../utils/response.utils';
import { AuthenticatedRequest } from '../middleware/auth.middleware';
import { logger } from '../config/logger';

// 1. Create New Order (Checkout)
export const createOrder = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const userId = req.user?.userId;
    if (!userId) return sendError(res, 'Unauthorized', null, 401);

    const {
      shippingAddress,
      items,
      paymentMethod = 'CREDIT_CARD',
      shippingFee = 0,
      discountAmount = 0,
    } = req.body;

    if (!items || items.length === 0) {
      return sendError(res, 'Order items list cannot be empty', null, 400);
    }

    let addressRecord = await prisma.shippingAddress.findFirst({
      where: {
        userId,
        street: shippingAddress.street,
        postalCode: shippingAddress.postalCode,
      },
    });

    if (!addressRecord) {
      addressRecord = await prisma.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: number, item: any) => {
      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 prisma.$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: any) => ({
              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 as string,
              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.info(`[Notification Engine] Sent Order Confirmation Email to User ${userId} for Order ${orderNumber}`);
    logger.info(`[SMS Gateway] Sent Order SMS notification to ${shippingAddress.phone}`);

    return sendSuccess(res, 'Order placed successfully!', order, 201);
  } catch (error: any) {
    return sendError(res, 'Failed to place order', error.message, 500);
  }
};

// 2. Get User Order History
export const getUserOrders = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const userId = req.user?.userId;
    if (!userId) return sendError(res, 'Unauthorized', null, 401);

    const orders = await prisma.order.findMany({
      where: { userId },
      include: {
        items: { include: { book: true } },
        shippingAddress: true,
        payment: true,
      },
      orderBy: { createdAt: 'desc' },
    });

    return sendSuccess(res, 'User order history retrieved', orders);
  } catch (error: any) {
    return sendError(res, 'Error fetching orders', error.message, 500);
  }
};

// 3. Get All Orders (Admin with Status Filter & Pagination)
export const getAllOrdersAdmin = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { status, limit = 20, page = 1 } = req.query;

    const take = Number(limit);
    const skip = (Number(page) - 1) * take;
    const where: any = {};
    if (status) where.status = String(status);

    const [orders, total] = await Promise.all([
      prisma.order.findMany({
        where,
        take,
        skip,
        include: {
          user: true,
          shippingAddress: true,
          payment: true,
          items: { include: { book: true } },
        },
        orderBy: { createdAt: 'desc' },
      }),
      prisma.order.count({ where }),
    ]);

    return sendSuccess(res, 'Admin orders list retrieved', {
      orders,
      pagination: { total, page: Number(page), limit: take, totalPages: Math.ceil(total / take) },
    });
  } catch (error: any) {
    return sendError(res, 'Error fetching admin orders', error.message, 500);
  }
};

// 4. Update Order Status (Admin Workflow: PENDING -> CONFIRMED -> PACKED -> SHIPPED -> DELIVERED / CANCELLED / RETURNED / REFUNDED)
export const updateOrderStatus = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    const { status, trackingNumber, carrier } = req.body;

    const order = await prisma.order.findUnique({
      where: { id },
      include: { user: true, shippingAddress: true },
    });

    if (!order) {
      return sendError(res, 'Order not found', null, 404);
    }

    const updatedOrder = await prisma.order.update({
      where: { id },
      data: {
        status: status as any,
      },
      include: { shippingAddress: true, payment: true },
    });

    // Log operational activity event
    await prisma.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.info(`[Notification Engine] Email notification sent to ${order.user.email} for status update: ${status}`);
    logger.info(`[SMS Gateway] SMS dispatch update sent to ${order.shippingAddress.phone}`);

    return sendSuccess(res, `Order status updated to '${status}'`, updatedOrder);
  } catch (error: any) {
    return sendError(res, 'Error updating order status', error.message, 500);
  }
};

// 5. Generate Shipping Label HTML / PDF Stub
export const getShippingLabel = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    const order = await prisma.order.findUnique({
      where: { id },
      include: { shippingAddress: true, items: { include: { book: true } } },
    });

    if (!order) return 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 sendSuccess(res, 'Shipping label generated', shippingLabelData);
  } catch (error: any) {
    return sendError(res, 'Shipping label generation failed', error.message, 500);
  }
};

// 6. Analytics & Order Performance Reports
export const getOrderReports = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const [statusCounts, totalRevenue] = await Promise.all([
      prisma.order.groupBy({
        by: ['status'],
        _count: { status: true },
      }),
      prisma.order.aggregate({
        _sum: { grandTotal: true },
        _count: { id: true },
      }),
    ]);

    return sendSuccess(res, 'Order analytics report generated', {
      totalOrdersCount: totalRevenue._count.id,
      totalRevenueSum: totalRevenue._sum.grandTotal ? Number(totalRevenue._sum.grandTotal) : 0,
      statusBreakdown: statusCounts,
    });
  } catch (error: any) {
    return sendError(res, 'Error generating order report', error.message, 500);
  }
};
