import { router, protectedProcedure } from "../trpc-index";
import { z } from "zod";
import { db } from "../../db/db_index";
import {
  orders,
  orderItems,
  orderStatus,
  addresses,
  productInfo,
  paymentInfoTable,
  coupons,
  couponUsage,
  payments,
  cartItems,
  refunds,
  units,
  userDetails,
} from "../../db/schema";
import { eq, and, inArray, desc, gte, lte } from "drizzle-orm";
import { generateSignedUrlsFromS3Urls } from "../../lib/s3-client";
import { ApiError } from "../../lib/api-error";
import {
  sendOrderPlacedNotification,
  sendOrderCancelledNotification,
} from "../../lib/notif-job";
import { RazorpayPaymentService } from "../../lib/payments-utils";
import { getNextDeliveryDate } from "../common-apis/common";
import { CONST_KEYS, getConstant, getConstants } from "../../lib/const-store";
import { publishFormattedOrder, publishCancellation } from "../../lib/post-order-handler";


const validateAndGetCoupon = async (
  couponId: number | undefined,
  userId: number,
  totalAmount: number
) => {
  if (!couponId) return null;

  const coupon = await db.query.coupons.findFirst({
    where: eq(coupons.id, couponId),
    with: {
      usages: { where: eq(couponUsage.userId, userId) },
    },
  });

  if (!coupon) throw new ApiError("Invalid coupon", 400);
  if (coupon.isInvalidated)
    throw new ApiError("Coupon is no longer valid", 400);
  if (coupon.validTill && new Date(coupon.validTill) < new Date())
    throw new ApiError("Coupon has expired", 400);
  if (
    coupon.maxLimitForUser &&
    coupon.usages.length >= coupon.maxLimitForUser
  )
    throw new ApiError("Coupon usage limit exceeded", 400);
  if (
    coupon.minOrder &&
    parseFloat(coupon.minOrder.toString()) > totalAmount
  )
    throw new ApiError(
      "Order amount does not meet coupon minimum requirement",
      400
    );

  return coupon;
};

const applyDiscountToOrder = (
  orderTotal: number,
  appliedCoupon: typeof coupons.$inferSelect | null,
  proportion: number
) => {
  let finalOrderTotal = orderTotal;
  // const proportion = totalAmount / orderTotal;
  if (appliedCoupon) {
    if (appliedCoupon.discountPercent) {
      const discount = Math.min(
        (orderTotal *
          parseFloat(appliedCoupon.discountPercent.toString())) /
          100,
        appliedCoupon.maxValue
          ? parseFloat(appliedCoupon.maxValue.toString()) * proportion
          : Infinity
      );
      finalOrderTotal -= discount;
    } else if (appliedCoupon.flatDiscount) {
      const discount = Math.min(
        parseFloat(appliedCoupon.flatDiscount.toString()) * proportion,
        appliedCoupon.maxValue
          ? parseFloat(appliedCoupon.maxValue.toString()) * proportion
          : finalOrderTotal
      );
      finalOrderTotal -= discount;
    }
  }

  // let orderDeliveryCharge = 0;
  // if (isFirstOrder && finalOrderTotal < minOrderValue) {
  //   orderDeliveryCharge = deliveryCharge;
  //   finalOrderTotal += deliveryCharge;
  // }


  return { finalOrderTotal, orderGroupProportion: proportion };
};

const placeOrderUtil = async (params: {
  userId: number;
  selectedItems: Array<{
    productId: number;
    quantity: number;
    slotId: number | null;
  }>;
  addressId: number;
  paymentMethod: "online" | "cod";
  couponId?: number;
  userNotes?: string;
  isFlash?: boolean;
}) => {
  const {
    userId,
    selectedItems,
    addressId,
    paymentMethod,
    couponId,
    userNotes,
  } = params;

  const constants = await getConstants<number>([
    CONST_KEYS.minRegularOrderValue,
    CONST_KEYS.deliveryCharge,
    CONST_KEYS.flashFreeDeliveryThreshold,
    CONST_KEYS.flashDeliveryCharge,
  ]);

  const minOrderValue = constants[CONST_KEYS.minRegularOrderValue] ?? 0;
  const deliveryCharge = constants[CONST_KEYS.deliveryCharge] ?? 0;

  const orderGroupId = `${Date.now()}-${userId}`;

  const address = await db.query.addresses.findFirst({
    where: and(eq(addresses.userId, userId), eq(addresses.id, addressId)),
  });
  if (!address) {
    throw new ApiError("Invalid address", 400);
  }

  const ordersBySlot = new Map<
    number | null,
    Array<{
      productId: number;
      quantity: number;
      slotId: number | null;
      product: any;
    }>
  >();

  for (const item of selectedItems) {
    const product = await db.query.productInfo.findFirst({
      where: eq(productInfo.id, item.productId),
    });
    if (!product) {
      throw new ApiError(`Product ${item.productId} not found`, 400);
    }

    if (!ordersBySlot.has(item.slotId)) {
      ordersBySlot.set(item.slotId, []);
    }
    ordersBySlot.get(item.slotId)!.push({ ...item, product });
  }

  if (params.isFlash) {
    for (const item of selectedItems) {
      const product = await db.query.productInfo.findFirst({
        where: eq(productInfo.id, item.productId),
      });
      if (!product?.isFlashAvailable) {
        throw new ApiError(`Product ${item.productId} is not available for flash delivery`, 400);
      }
    }
  }

  let totalAmount = 0;
  for (const [slotId, items] of ordersBySlot) {
    const orderTotal = items.reduce(
      (sum, item) => {
        const itemPrice = params.isFlash
          ? parseFloat((item.product.flashPrice || item.product.price).toString())
          : parseFloat(item.product.price.toString());
        return sum + itemPrice * item.quantity;
      },
      0
    );
    totalAmount += orderTotal;
  }

  const appliedCoupon = await validateAndGetCoupon(couponId, userId, totalAmount);

  const expectedDeliveryCharge =
    totalAmount < minOrderValue ? deliveryCharge : 0;

  const totalWithDelivery = totalAmount + expectedDeliveryCharge;

  type OrderData = {
    order: Omit<typeof orders.$inferInsert, "id">;
    orderItems: Omit<typeof orderItems.$inferInsert, "id">[];
    orderStatus: Omit<typeof orderStatus.$inferInsert, "id">;
  };

  const ordersData: OrderData[] = [];
  let isFirstOrder = true;

  for (const [slotId, items] of ordersBySlot) {
    const subOrderTotal = items.reduce(
      (sum, item) => {
        const itemPrice = params.isFlash
          ? parseFloat((item.product.flashPrice || item.product.price).toString())
          : parseFloat(item.product.price.toString());
        return sum + itemPrice * item.quantity;
      },
      0
    );
    const subOrderTotalWithDelivery = subOrderTotal + expectedDeliveryCharge;

    const orderGroupProportion = subOrderTotal / totalAmount;
    const orderTotalAmount = isFirstOrder ? subOrderTotalWithDelivery : subOrderTotal;

    const { finalOrderTotal: finalOrderAmount } = applyDiscountToOrder(
      orderTotalAmount,
      appliedCoupon,
      orderGroupProportion
    );

    const order: Omit<typeof orders.$inferInsert, "id"> = {
      userId,
      addressId,
      slotId: params.isFlash ? null : slotId,
      isCod: paymentMethod === "cod",
      isOnlinePayment: paymentMethod === "online",
      paymentInfoId: null,
      totalAmount: finalOrderAmount.toString(),
      deliveryCharge: isFirstOrder ? expectedDeliveryCharge.toString() : "0",
      readableId: -1,
      userNotes: userNotes || null,
      orderGroupId,
      orderGroupProportion: orderGroupProportion.toString(),
      isFlashDelivery: params.isFlash,
    };

    const orderItemsData: Omit<typeof orderItems.$inferInsert, "id">[] = items.map(
      (item) => ({
        orderId: 0,
        productId: item.productId,
        quantity: item.quantity.toString(),
        price: params.isFlash
          ? item.product.flashPrice || item.product.price
          : item.product.price,
        discountedPrice: (
          params.isFlash
            ? item.product.flashPrice || item.product.price
            : item.product.price
        ).toString(),
      })
    );

    const orderStatusData: Omit<typeof orderStatus.$inferInsert, "id"> = {
      userId,
      orderId: 0,
      paymentStatus: paymentMethod === "cod" ? "cod" : "pending",
    };

    ordersData.push({ order, orderItems: orderItemsData, orderStatus: orderStatusData });
    isFirstOrder = false;
  }

  const createdOrders = await db.transaction(async (tx) => {
    let sharedPaymentInfoId: number | null = null;
    if (paymentMethod === "online") {
      const [paymentInfo] = await tx
        .insert(paymentInfoTable)
        .values({
          status: "pending",
          gateway: "razorpay",
          merchantOrderId: `multi_order_${Date.now()}`,
        })
        .returning();
      sharedPaymentInfoId = paymentInfo.id;
    }

    const ordersToInsert: Omit<typeof orders.$inferInsert, "id">[] = ordersData.map(
      (od) => ({
        ...od.order,
        paymentInfoId: sharedPaymentInfoId,
      })
    );

    const insertedOrders = await tx.insert(orders).values(ordersToInsert).returning();

    const allOrderItems: Omit<typeof orderItems.$inferInsert, "id">[] = [];
    const allOrderStatuses: Omit<typeof orderStatus.$inferInsert, "id">[] = [];

    insertedOrders.forEach((order, index) => {
      const od = ordersData[index];
      od.orderItems.forEach((item) => {
        allOrderItems.push({ ...item, orderId: order.id as number });
      });
      allOrderStatuses.push({
        ...od.orderStatus,
        orderId: order.id as number,
      });
    });

    await tx.insert(orderItems).values(allOrderItems);
    await tx.insert(orderStatus).values(allOrderStatuses);

    if (paymentMethod === "online" && sharedPaymentInfoId) {
      const razorpayOrder = await RazorpayPaymentService.createOrder(
        sharedPaymentInfoId,
        totalWithDelivery.toString()
      );
      await RazorpayPaymentService.insertPaymentRecord(
        sharedPaymentInfoId,
        razorpayOrder,
        tx
      );
    }

    return insertedOrders;
  });

  await db.delete(cartItems).where(
    and(
      eq(cartItems.userId, userId),
      inArray(
        cartItems.productId,
        selectedItems.map((item) => item.productId)
      )
    )
  );

  if (appliedCoupon && createdOrders.length > 0) {
    await db.insert(couponUsage).values({
      userId,
      couponId: appliedCoupon.id,
      orderId: createdOrders[0].id as number,
      orderItemId: null,
      usedAt: new Date(),
    });
  }

  for (const order of createdOrders) {
    sendOrderPlacedNotification(userId, order.id.toString());
  }

  await publishFormattedOrder(createdOrders, ordersBySlot);

  return { success: true, data: createdOrders };
};

export const orderRouter = router({
  placeOrder: protectedProcedure
    .input(
      z.object({
        selectedItems: z.array(
          z.object({
            productId: z.number().int().positive(),
            quantity: z.number().int().positive(),
            slotId: z.union([z.number().int(), z.null()]),
          })
        ),
        addressId: z.number().int().positive(),
        paymentMethod: z.enum(["online", "cod"]),
        couponId: z.number().int().positive().optional(),
        userNotes: z.string().optional(),
        isFlashDelivery: z.boolean().optional().default(false),
      })
    )
    .mutation(async ({ input, ctx }) => {
      const userId = ctx.user.userId;

      // Check if user is suspended from placing orders
      const userDetail = await db.query.userDetails.findFirst({
        where: eq(userDetails.userId, userId),
      });

      if (userDetail?.isSuspended) {
        throw new ApiError("Unable to place order", 403);
      }

      const {
        selectedItems,
        addressId,
        paymentMethod,
        couponId,
        userNotes,
        isFlashDelivery,
      } = input;

      // Check if flash delivery is enabled when placing a flash delivery order
      if (isFlashDelivery) {
        const isFlashDeliveryEnabled = await getConstant<boolean>(CONST_KEYS.isFlashDeliveryEnabled);
        if (!isFlashDeliveryEnabled) {
          throw new ApiError("Flash delivery is currently unavailable. Please opt for scheduled delivery.", 403);
        }
      }

      let processedItems = selectedItems;

      // Handle flash delivery slot resolution
      if (isFlashDelivery) {
        // For flash delivery, set slotId to null (no specific slot assigned)
        processedItems = selectedItems.map(item => ({
          ...item,
          slotId: null as any, // Type override for flash delivery
        }));
      }
      
      return await placeOrderUtil({
        userId,
        selectedItems: processedItems,
        addressId,
        paymentMethod,
        couponId,
        userNotes,
        isFlash: isFlashDelivery,
      });
    }),

  getOrders: protectedProcedure
    .input(
      z
        .object({
          page: z.number().min(1).default(1),
          pageSize: z.number().min(1).max(50).default(10),
        })
        .optional()
    )
    .query(async ({ input, ctx }) => {
      const { page = 1, pageSize = 10 } = input || {};
      const userId = ctx.user.userId;
      const offset = (page - 1) * pageSize;

      // Get total count for pagination
      const totalCountResult = await db.$count(
        orders,
        eq(orders.userId, userId)
      );
      const totalCount = totalCountResult;

      const userOrders = await db.query.orders.findMany({
        where: eq(orders.userId, userId),
        with: {
          orderItems: {
            with: {
              product: true,
            },
          },
          slot: true,
          paymentInfo: true,
          orderStatus: true,
          refunds: true,
        },
        orderBy: (orders, { desc }) => [desc(orders.createdAt)],
        limit: pageSize,
        offset: offset,
      });

      const mappedOrders = await Promise.all(
        userOrders.map(async (order) => {
          const status = order.orderStatus[0];
          const refund = order.refunds[0];

          type DeliveryStatus = "cancelled" | "success" | "pending" | "packaged";
          type OrderStatus = "cancelled" | "success";

          let deliveryStatus: DeliveryStatus;
          let orderStatus: OrderStatus;

          const allItemsPackaged = order.orderItems.every(
            (item) => item.is_packaged
          );

          if (status?.isCancelled) {
            deliveryStatus = "cancelled";
            orderStatus = "cancelled";
          } else if (status?.isDelivered) {
            deliveryStatus = "success";
            orderStatus = "success";
          } else if (allItemsPackaged) {
            deliveryStatus = "packaged";
            orderStatus = "success";
          } else {
            deliveryStatus = "pending";
            orderStatus = "success";
          }

          const paymentMode = order.isCod ? "CoD" : "Online";
          const paymentStatus = status?.paymentStatus || "pending";
          const refundStatus = refund?.refundStatus || "none";
          const refundAmount = refund?.refundAmount
            ? parseFloat(refund.refundAmount.toString())
            : null;

          const items = await Promise.all(
            order.orderItems.map(async (item) => {

              const signedImages = item.product.images
                ? await generateSignedUrlsFromS3Urls(
                    item.product.images as string[]
                  )
                : [];
              return {
                productName: item.product.name,
                quantity: parseFloat(item.quantity),
                price: parseFloat(item.price.toString()),
                discountedPrice: parseFloat(
                  item.discountedPrice?.toString() || item.price.toString()
                ),
                amount:
                  parseFloat(item.price.toString()) * parseFloat(item.quantity),
                image: signedImages[0] || null,
              };
            })
          );

          return {
            id: order.id,
            orderId: `ORD${order.id}`,
            orderDate: order.createdAt.toISOString(),
            deliveryStatus,
            deliveryDate: order.slot?.deliveryTime.toISOString(),
            orderStatus,
            cancelReason: status?.cancelReason || null,
            paymentMode,
            totalAmount: Number(order.totalAmount),
            deliveryCharge: Number(order.deliveryCharge),
            paymentStatus,
            refundStatus,
            refundAmount,
            userNotes: order.userNotes || null,
            items,
            isFlashDelivery: order.isFlashDelivery,
            createdAt: order.createdAt.toISOString(),
          };
        })
      );

      return {
        success: true,
        data: mappedOrders,
        pagination: {
          page,
          pageSize,
          totalCount,
          totalPages: Math.ceil(totalCount / pageSize),
        },
      };
    }),

  getOrderById: protectedProcedure
    .input(z.object({ orderId: z.string() }))
    .query(async ({ input, ctx }) => {
      const { orderId } = input;
      const userId = ctx.user.userId;

      const order = await db.query.orders.findFirst({
        where: and(eq(orders.id, parseInt(orderId)), eq(orders.userId, userId)),
        with: {
          orderItems: {
            with: {
              product: true,
            },
          },
          slot: true,
          paymentInfo: true,
          orderStatus: {
            with: {
              refundCoupon: true,
            },
          },
          refunds: true,
        },
      });

      if (!order) {
        throw new Error("Order not found");
      }

      // Get coupon usage for this specific order using new orderId field
      const couponUsageData = await db.query.couponUsage.findMany({
        where: eq(couponUsage.orderId, order.id), // Use new orderId field
        with: {
          coupon: true,
        },
      });

      let couponData = null;
      if (couponUsageData.length > 0) {
        // Calculate total discount from multiple coupons
        let totalDiscountAmount = 0;
        const orderTotal = parseFloat(order.totalAmount.toString());

        for (const usage of couponUsageData) {
          let discountAmount = 0;

          if (usage.coupon.discountPercent) {
            discountAmount =
              (orderTotal *
                parseFloat(usage.coupon.discountPercent.toString())) /
              100;
          } else if (usage.coupon.flatDiscount) {
            discountAmount = parseFloat(usage.coupon.flatDiscount.toString());
          }

          // Apply max value limit if set
          if (
            usage.coupon.maxValue &&
            discountAmount > parseFloat(usage.coupon.maxValue.toString())
          ) {
            discountAmount = parseFloat(usage.coupon.maxValue.toString());
          }

          totalDiscountAmount += discountAmount;
        }

        couponData = {
          couponCode: couponUsageData
            .map((u) => u.coupon.couponCode)
            .join(", "),
          couponDescription: `${couponUsageData.length} coupons applied`,
          discountAmount: totalDiscountAmount,
        };
      }

      const status = order.orderStatus[0];
      const refund = order.refunds[0];

      type DeliveryStatus = "cancelled" | "success" | "pending" | "packaged";
      type OrderStatus = "cancelled" | "success";

      let deliveryStatus: DeliveryStatus;
      let orderStatus: OrderStatus;

      const allItemsPackaged = order.orderItems.every(
        (item) => item.is_packaged
      );

      if (status?.isCancelled) {
        deliveryStatus = "cancelled";
        orderStatus = "cancelled";
      } else if (status?.isDelivered) {
        deliveryStatus = "success";
        orderStatus = "success";
      } else if (allItemsPackaged) {
        deliveryStatus = "packaged";
        orderStatus = "success";
      } else {
        deliveryStatus = "pending";
        orderStatus = "success";
      }

      const paymentMode = order.isCod ? "CoD" : "Online";
      const paymentStatus = status?.paymentStatus || "pending";
      const refundStatus = refund?.refundStatus || "none";
      const refundAmount = refund?.refundAmount
        ? parseFloat(refund.refundAmount.toString())
        : null;

      const items = await Promise.all(
        order.orderItems.map(async (item) => {
          const signedImages = item.product.images
            ? await generateSignedUrlsFromS3Urls(
                item.product.images as string[]
              )
            : [];
          return {
            productName: item.product.name,
            quantity: parseFloat(item.quantity),
            price: parseFloat(item.price.toString()),
            discountedPrice: parseFloat(
              item.discountedPrice?.toString() || item.price.toString()
            ),
            amount:
              parseFloat(item.price.toString()) * parseFloat(item.quantity),
            image: signedImages[0] || null,
          };
        })
      );

      return {
        id: order.id,
        orderId: `ORD${order.id}`,
        orderDate: order.createdAt.toISOString(),
        deliveryStatus,
        deliveryDate: order.slot?.deliveryTime.toISOString(),
        orderStatus: order.orderStatus,
        cancellationStatus: orderStatus,
        cancelReason: status?.cancelReason || null,
        paymentMode,
        paymentStatus,
        refundStatus,
        refundAmount,
        userNotes: order.userNotes || null,
        items,
        couponCode: couponData?.couponCode || null,
        couponDescription: couponData?.couponDescription || null,
        discountAmount: couponData?.discountAmount || null,
        orderAmount: parseFloat(order.totalAmount.toString()),
        isFlashDelivery: order.isFlashDelivery,
        createdAt: order.createdAt.toISOString(),
      };
    }),

  cancelOrder: protectedProcedure
    .input(
      z.object({
        // id: z.string().regex(/^ORD\d+$/, "Invalid order ID format"),
        id: z.number(),
        reason: z.string().min(1, "Cancellation reason is required"),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        const userId = ctx.user.userId;
        const { id, reason } = input;

        // Check if order exists and belongs to user
        const order = await db.query.orders.findFirst({
          where: eq(orders.id, Number(id)),
          with: {
            orderStatus: true,
          },
        });

        if (!order) {
          console.error("Order not found:", id);
          throw new ApiError("Order not found", 404);
        }

        if (order.userId !== userId) {
          console.error("Order does not belong to user:", {
            orderId: id,
            orderUserId: order.userId,
            requestUserId: userId,
          });

          throw new ApiError("Order not found", 404);
        }

        const status = order.orderStatus[0];
        if (!status) {
          console.error("Order status not found for order:", id);
          throw new ApiError("Order status not found", 400);
        }

        if (status.isCancelled) {
          console.error("Order is already cancelled:", id);
          throw new ApiError("Order is already cancelled", 400);
        }

        if (status.isDelivered) {
          console.error("Cannot cancel delivered order:", id);
          throw new ApiError("Cannot cancel delivered order", 400);
        }

        // Perform database operations in transaction
        const result = await db.transaction(async (tx) => {
          // Update order status
          await tx
            .update(orderStatus)
            .set({
              isCancelled: true,
              cancelReason: reason,
              cancellationUserNotes: reason,
              cancellationReviewed: false,
            })
            .where(eq(orderStatus.id, status.id));

          // Determine refund status based on payment method
          const refundStatus = order.isCod ? "na" : "pending";

          // Insert refund record
          await tx.insert(refunds).values({
            orderId: order.id,
            refundStatus,
          });

          return { orderId: order.id, userId };
        });

        // Send notification outside transaction (idempotent operation)
        await sendOrderCancelledNotification(
          result.userId,
          result.orderId.toString()
        );

        // Publish to Redis for Telegram notification
        await publishCancellation(result.orderId, 'user', reason);

        return { success: true, message: "Order cancelled successfully" };
      } catch (e) {
        console.log(e);
        throw new ApiError("failed to cancel order");
      }
    }),

  updateUserNotes: protectedProcedure
    .input(
      z.object({
        id: z.number(),
        userNotes: z.string(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      const userId = ctx.user.userId;
      const { id, userNotes } = input;

      // Extract readable ID from orderId (e.g., ORD001 -> 1)
      //  const readableIdMatch = id.match(/^ORD(\d+)$/);
      //  if (!readableIdMatch) {
      //    console.error("Invalid order ID format:", id);
      //    throw new ApiError("Invalid order ID format", 400);
      //  }
      //  const readableId = parseInt(readableIdMatch[1]);

      // Check if order exists and belongs to user
      const order = await db.query.orders.findFirst({
        where: eq(orders.id, Number(id)),
        with: {
          orderStatus: true,
        },
      });

      if (!order) {
        console.error("Order not found:", id);
        throw new ApiError("Order not found", 404);
      }

      if (order.userId !== userId) {
        console.error("Order does not belong to user:", {
          orderId: id,
          orderUserId: order.userId,
          requestUserId: userId,
        });
        throw new ApiError("Order not found", 404);
      }

      const status = order.orderStatus[0];
      if (!status) {
        console.error("Order status not found for order:", id);
        throw new ApiError("Order status not found", 400);
      }

      // Only allow updating notes for orders that are not delivered or cancelled
      if (status.isDelivered) {
        console.error("Cannot update notes for delivered order:", id);
        throw new ApiError("Cannot update notes for delivered order", 400);
      }

      if (status.isCancelled) {
        console.error("Cannot update notes for cancelled order:", id);
        throw new ApiError("Cannot update notes for cancelled order", 400);
      }

      // Update user notes
      await db
        .update(orders)
        .set({
          userNotes: userNotes || null,
        })
        .where(eq(orders.id, order.id));

      return { success: true, message: "Notes updated successfully" };
    }),

  getRecentlyOrderedProducts: protectedProcedure
    .input(
      z
        .object({
          limit: z.number().min(1).max(50).default(20),
        })
        .optional()
    )
    .query(async ({ input, ctx }) => {
      const { limit = 20 } = input || {};
      const userId = ctx.user.userId;

      // Get user's recent delivered orders (last 30 days)
      const thirtyDaysAgo = new Date();
      thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

      const recentOrders = await db
        .select({ id: orders.id })
        .from(orders)
        .innerJoin(orderStatus, eq(orders.id, orderStatus.orderId))
        .where(
          and(
            eq(orders.userId, userId),
            eq(orderStatus.isDelivered, true),
            gte(orders.createdAt, thirtyDaysAgo)
          )
        )
        .orderBy(desc(orders.createdAt))
        .limit(10); // Get last 10 orders

      if (recentOrders.length === 0) {
        return { success: true, products: [] };
      }

      const orderIds = recentOrders.map((order) => order.id);

      // Get unique product IDs from recent orders
      const orderItemsResult = await db
        .select({ productId: orderItems.productId })
        .from(orderItems)
        .where(inArray(orderItems.orderId, orderIds));

      const productIds = [
        ...new Set(orderItemsResult.map((item) => item.productId)),
      ];

      if (productIds.length === 0) {
        return { success: true, products: [] };
      }

      // Get product details
      const productsWithUnits = await db
        .select({
          id: productInfo.id,
          name: productInfo.name,
          shortDescription: productInfo.shortDescription,
          price: productInfo.price,
          images: productInfo.images,
          isOutOfStock: productInfo.isOutOfStock,
          unitShortNotation: units.shortNotation,
          incrementStep: productInfo.incrementStep,
        })
        .from(productInfo)
        .innerJoin(units, eq(productInfo.unitId, units.id))
        .where(
          and(
            inArray(productInfo.id, productIds),
            eq(productInfo.isSuspended, false)
          )
        )
        .orderBy(desc(productInfo.createdAt))
        .limit(limit);

      // Generate signed URLs for product images
      const formattedProducts = await Promise.all(
        productsWithUnits.map(async (product) => {
          const nextDeliveryDate = await getNextDeliveryDate(product.id);
          return {
            id: product.id,
            name: product.name,
            shortDescription: product.shortDescription,
            price: product.price,
            unit: product.unitShortNotation,
            incrementStep: product.incrementStep,
            isOutOfStock: product.isOutOfStock,
            nextDeliveryDate: nextDeliveryDate
              ? nextDeliveryDate.toISOString()
              : null,
            images: await generateSignedUrlsFromS3Urls(
              (product.images as string[]) || []
            ),
          };
        })
      );

      return {
        success: true,
        products: formattedProducts,
      };
    }),
});
