import { router, protectedProcedure } from "../trpc-index";
import { z } from "zod";
import { db } from "../../db/db_index";
import {
  orders,
  orderItems,
  orderStatus,
  users,
  addresses,
  refunds,
  coupons,
  couponUsage,
} from "../../db/schema";
import { eq, and, gte, lt, desc, SQL, inArray } from "drizzle-orm";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import { ApiError } from "../../lib/api-error";
import {
  sendOrderPackagedNotification,
  sendOrderDeliveredNotification,
} from "../../lib/notif-job";
import { publishCancellation } from "../../lib/post-order-handler";

const updateOrderNotesSchema = z.object({
  orderId: z.number(),
  adminNotes: z.string(),
});

const getFullOrderSchema = z.object({
  orderId: z.number(),
});

const getOrderDetailsSchema = z.object({
  orderId: z.number(),
});

const updatePackagedSchema = z.object({
  orderId: z.string(),
  isPackaged: z.boolean(),
});

const updateDeliveredSchema = z.object({
  orderId: z.string(),
  isDelivered: z.boolean(),
});

const updateOrderItemPackagingSchema = z.object({
  orderItemId: z.number(),
  isPackaged: z.boolean().optional(),
  isPackageVerified: z.boolean().optional(),
});

const getSlotOrdersSchema = z.object({
  slotId: z.string(),
});

const getTodaysOrdersSchema = z.object({
  slotId: z.string().optional(),
});

const getAllOrdersSchema = z.object({
  cursor: z.number().optional(),
  limit: z.number().default(20),
  slotId: z.number().optional().nullable(),
  packagedFilter: z
    .enum(["all", "packaged", "not_packaged"])
    .optional()
    .default("all"),
  deliveredFilter: z
    .enum(["all", "delivered", "not_delivered"])
    .optional()
    .default("all"),
  cancellationFilter: z
    .enum(["all", "cancelled", "not_cancelled"])
    .optional()
    .default("all"),
  flashDeliveryFilter: z
    .enum(["all", "flash", "regular"])
    .optional()
    .default("all"),
});

export const orderRouter = router({
  updateNotes: protectedProcedure
    .input(updateOrderNotesSchema)
    .mutation(async ({ input }) => {
      const { orderId, adminNotes } = input;

      const result = await db
        .update(orders)
        .set({
          adminNotes: adminNotes || null,
        })
        .where(eq(orders.id, orderId))
        .returning();

      if (result.length === 0) {
        throw new Error("Order not found");
      }

      return result[0];
    }),

  getFullOrder: protectedProcedure
    .input(getFullOrderSchema)
    .query(async ({ input }) => {
      const { orderId } = input;

      const orderData = await db.query.orders.findFirst({
        where: eq(orders.id, orderId),
        with: {
          user: true,
          address: true,
          slot: true,
          orderItems: {
            with: {
              product: {
                with: {
                  unit: true,
                },
              },
            },
          },
          payment: true,
          paymentInfo: true,
        },
      });

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

      // Get order status separately
      const statusRecord = await db.query.orderStatus.findFirst({
        where: eq(orderStatus.orderId, orderId),
      });

      let status: "pending" | "delivered" | "cancelled" = "pending";
      if (statusRecord?.isCancelled) {
        status = "cancelled";
      } else if (statusRecord?.isDelivered) {
        status = "delivered";
      }

      // Get refund details if order is cancelled
      let refund = null;
      if (status === "cancelled") {
        refund = await db.query.refunds.findFirst({
          where: eq(refunds.orderId, orderId),
        });
      }

      return {
        id: orderData.id,
        readableId: orderData.id,
        customerName: `${orderData.user.name}`,
        customerEmail: orderData.user.email,
        customerMobile: orderData.user.mobile,
        address: {
          line1: orderData.address.addressLine1,
          line2: orderData.address.addressLine2,
          city: orderData.address.city,
          state: orderData.address.state,
          pincode: orderData.address.pincode,
          phone: orderData.address.phone,
        },
        slotInfo: orderData.slot
          ? {
              time: orderData.slot.deliveryTime.toISOString(),
              sequence: orderData.slot.deliverySequence,
            }
          : null,
        isCod: orderData.isCod,
        isOnlinePayment: orderData.isOnlinePayment,
        totalAmount: orderData.totalAmount,
        adminNotes: orderData.adminNotes,
        userNotes: orderData.userNotes,
        createdAt: orderData.createdAt,
        status,
        isPackaged:
          orderData.orderItems.every((item) => item.is_packaged) || false,
        isDelivered: statusRecord?.isDelivered || false,
        items: orderData.orderItems.map((item) => ({
          id: item.id,
          name: item.product.name,
          quantity: item.quantity,
          price: item.price,
          unit: item.product.unit?.shortNotation,
          amount:
            parseFloat(item.price.toString()) *
            parseFloat(item.quantity || "0"),
        })),
        payment: orderData.payment
          ? {
              status: orderData.payment.status,
              gateway: orderData.payment.gateway,
              merchantOrderId: orderData.payment.merchantOrderId,
            }
          : null,
        paymentInfo: orderData.paymentInfo
          ? {
              status: orderData.paymentInfo.status,
              gateway: orderData.paymentInfo.gateway,
              merchantOrderId: orderData.paymentInfo.merchantOrderId,
            }
          : null,
        // Cancellation details (only present for cancelled orders)
        cancelReason: statusRecord?.cancelReason || null,
        cancellationReviewed: statusRecord?.cancellationReviewed || false,
        isRefundDone: refund?.refundStatus === "processed" || false,
      };
    }),

  getOrderDetails: protectedProcedure
    .input(getOrderDetailsSchema)
    .query(async ({ input }) => {
      const { orderId } = input;

      // Single optimized query with all relations
      const orderData = await db.query.orders.findFirst({
        where: eq(orders.id, orderId),
        with: {
          user: true,
          address: true,
          slot: true,
          orderItems: {
            with: {
              product: {
                with: {
                  unit: true,
                },
              },
            },
          },
          payment: true,
          paymentInfo: true,
          orderStatus: true, // Include in main query
          refunds: true, // Include in main query
        },
      });

      if (!orderData) {
        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, orderData.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(orderData.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,
        };
      }

      // Status determination from included relation
      const statusRecord = orderData.orderStatus?.[0];
      let status: "pending" | "delivered" | "cancelled" = "pending";
      if (statusRecord?.isCancelled) {
        status = "cancelled";
      } else if (statusRecord?.isDelivered) {
        status = "delivered";
      }

      // Always include refund data (will be null/undefined if not cancelled)
      const refund = orderData.refunds?.[0];

      return {
        id: orderData.id,
        readableId: orderData.id,
        userId: orderData.user.id,
        customerName: `${orderData.user.name}`,
        customerEmail: orderData.user.email,
        customerMobile: orderData.user.mobile,
        address: {
          name: orderData.address.name,
          line1: orderData.address.addressLine1,
          line2: orderData.address.addressLine2,
          city: orderData.address.city,
          state: orderData.address.state,
          pincode: orderData.address.pincode,
          phone: orderData.address.phone,
        },
        slotInfo: orderData.slot
          ? {
              time: orderData.slot.deliveryTime.toISOString(),
              sequence: orderData.slot.deliverySequence,
            }
          : null,
        isCod: orderData.isCod,
        isOnlinePayment: orderData.isOnlinePayment,
        totalAmount: orderData.totalAmount,
        adminNotes: orderData.adminNotes,
        userNotes: orderData.userNotes,
        createdAt: orderData.createdAt,
        status,
        isPackaged: statusRecord?.isPackaged || false,
        isDelivered: statusRecord?.isDelivered || false,
        items: orderData.orderItems.map((item) => ({
          id: item.id,
          name: item.product.name,
          quantity: item.quantity,
          productSize: item.product.productQuantity,
          price: item.price,
          unit: item.product.unit?.shortNotation,
          amount:
            parseFloat(item.price.toString()) *
            parseFloat(item.quantity || "0"),
          isPackaged: item.is_packaged,
          isPackageVerified: item.is_package_verified,
        })),
        payment: orderData.payment
          ? {
              status: orderData.payment.status,
              gateway: orderData.payment.gateway,
              merchantOrderId: orderData.payment.merchantOrderId,
            }
          : null,
        paymentInfo: orderData.paymentInfo
          ? {
              status: orderData.paymentInfo.status,
              gateway: orderData.paymentInfo.gateway,
              merchantOrderId: orderData.paymentInfo.merchantOrderId,
            }
          : null,
        // Cancellation details (always included, null if not cancelled)
        cancelReason: statusRecord?.cancelReason || null,
        cancellationReviewed: statusRecord?.cancellationReviewed || false,
        isRefundDone: refund?.refundStatus === "processed" || false,
        refundStatus: refund?.refundStatus as RefundStatus,
        refundAmount: refund?.refundAmount
          ? parseFloat(refund.refundAmount.toString())
          : null,
        // Coupon information
        couponData: couponData,
        couponCode: couponData?.couponCode || null,
        couponDescription: couponData?.couponDescription || null,
        discountAmount: couponData?.discountAmount || null,
        orderStatus: statusRecord,
        refundRecord: refund,
        isFlashDelivery: orderData.isFlashDelivery,
      };
    }),

  updatePackaged: protectedProcedure
    .input(updatePackagedSchema)
    .mutation(async ({ input }) => {
      const { orderId, isPackaged } = input;

      // Update all order items to the specified packaged state
      await db
        .update(orderItems)
        .set({ is_packaged: isPackaged })
        .where(eq(orderItems.orderId, parseInt(orderId)));

      // Also update the order status table for backward compatibility
      if (!isPackaged) {
        await db
          .update(orderStatus)
          .set({ isPackaged, isDelivered: false })
          .where(eq(orderStatus.orderId, parseInt(orderId)));
      } else {
        await db
          .update(orderStatus)
          .set({ isPackaged })
          .where(eq(orderStatus.orderId, parseInt(orderId)));
      }

      const order = await db.query.orders.findFirst({
        where: eq(orders.id, parseInt(orderId)),
      });
      if (order) await sendOrderPackagedNotification(order.userId, orderId);

      return { success: true };
    }),

  updateDelivered: protectedProcedure
    .input(updateDeliveredSchema)
    .mutation(async ({ input }) => {
      const { orderId, isDelivered } = input;

      await db
        .update(orderStatus)
        .set({ isDelivered })
        .where(eq(orderStatus.orderId, parseInt(orderId)));

      const order = await db.query.orders.findFirst({
        where: eq(orders.id, parseInt(orderId)),
      });
      if (order) await sendOrderDeliveredNotification(order.userId, orderId);

      return { success: true };
    }),

  updateOrderItemPackaging: protectedProcedure
    .input(updateOrderItemPackagingSchema)
    .mutation(async ({ input }) => {
      const { orderItemId, isPackaged, isPackageVerified } = input;

      // Validate that orderItem exists
      const orderItem = await db.query.orderItems.findFirst({
        where: eq(orderItems.id, orderItemId),
      });

      if (!orderItem) {
        throw new ApiError("Order item not found", 404);
      }

      // Build update object with only provided fields
      const updateData: any = {};
      if (isPackaged !== undefined) {
        updateData.is_packaged = isPackaged;
      }
      if (isPackageVerified !== undefined) {
        updateData.is_package_verified = isPackageVerified;
      }

      // Update the order item
      await db
        .update(orderItems)
        .set(updateData)
        .where(eq(orderItems.id, orderItemId));

      return { success: true };
    }),

  getSlotOrders: protectedProcedure
    .input(getSlotOrdersSchema)
    .query(async ({ input }) => {
      const { slotId } = input;

      const slotOrders = await db.query.orders.findMany({
        where: eq(orders.slotId, parseInt(slotId)),
        with: {
          user: true,
          address: true,
          slot: true,
          orderItems: {
            with: {
              product: {
                with: {
                  unit: true,
                },
              },
            },
          },
          orderStatus: true,
        },
      });

      const filteredOrders = slotOrders.filter((order) => {
        const statusRecord = order.orderStatus[0];
        return (
          order.isCod ||
          (statusRecord && statusRecord.paymentStatus === "success")
        );
      });

      const formattedOrders = filteredOrders.map((order) => {
        const statusRecord = order.orderStatus[0]; // assuming one status per order
        let status: "pending" | "delivered" | "cancelled" = "pending";
        if (statusRecord?.isCancelled) {
          status = "cancelled";
        } else if (statusRecord?.isDelivered) {
          status = "delivered";
        }

        const items = order.orderItems.map((item) => ({
          id: item.id,
          name: item.product.name,
          quantity: parseFloat(item.quantity),
          price: parseFloat(item.price.toString()),
          amount: parseFloat(item.quantity) * parseFloat(item.price.toString()),
          unit: item.product.unit?.shortNotation || "",
          isPackaged: item.is_packaged,
          isPackageVerified: item.is_package_verified,
        }));

        return {
          id: order.id,
          readableId: order.id,
          customerName: order.user.name,
          address: `${order.address.addressLine1}${
            order.address.addressLine2 ? `, ${order.address.addressLine2}` : ""
          }, ${order.address.city}, ${order.address.state} - ${
            order.address.pincode
          }, Phone: ${order.address.phone}`,
           addressId: order.addressId,
           latitude: order.address.adminLatitude ?? order.address.latitude,
           longitude: order.address.adminLongitude ?? order.address.longitude,
          totalAmount: parseFloat(order.totalAmount),
          items,
          deliveryTime: order.slot?.deliveryTime.toISOString() || null,
          status,
          isPackaged:
            order.orderItems.every((item) => item.is_packaged) || false,
          isDelivered: statusRecord?.isDelivered || false,
          isCod: order.isCod,
          paymentMode: order.isCod ? "COD" : "Online",
          paymentStatus: statusRecord?.paymentStatus || "pending",
          slotId: order.slotId,
          adminNotes: order.adminNotes,
          userNotes: order.userNotes,
        };
      });

      return { success: true, data: formattedOrders };
    }),

  getTodaysOrders: protectedProcedure
    .input(getTodaysOrdersSchema)
    .query(async ({ input }) => {
      const { slotId } = input;
      const start = dayjs().startOf("day").toDate();
      const end = dayjs().endOf("day").toDate();

      let whereCondition = and(
        gte(orders.createdAt, start),
        lt(orders.createdAt, end)
      );

      if (slotId) {
        whereCondition = and(
          whereCondition,
          eq(orders.slotId, parseInt(slotId))
        );
      }

      const todaysOrders = await db.query.orders.findMany({
        where: whereCondition,
        with: {
          user: true,
          address: true,
          slot: true,
          orderItems: {
            with: {
              product: {
                with: {
                  unit: true,
                },
              },
            },
          },
          orderStatus: true,
        },
      });

      const filteredOrders = todaysOrders.filter((order) => {
        const statusRecord = order.orderStatus[0];
        return (
          order.isCod ||
          (statusRecord && statusRecord.paymentStatus === "success")
        );
      });

      const formattedOrders = filteredOrders.map((order) => {
        const statusRecord = order.orderStatus[0]; // assuming one status per order
        let status: "pending" | "delivered" | "cancelled" = "pending";
        if (statusRecord?.isCancelled) {
          status = "cancelled";
        } else if (statusRecord?.isDelivered) {
          status = "delivered";
        }

        const items = order.orderItems.map((item) => ({
          name: item.product.name,
          quantity: parseFloat(item.quantity),
          price: parseFloat(item.price.toString()),
          amount: parseFloat(item.quantity) * parseFloat(item.price.toString()),
          unit: item.product.unit?.shortNotation || "",
        }));

        return {
          orderId: order.id.toString(),
          readableId: order.id,
          customerName: order.user.name,
          address: `${order.address.addressLine1}${
            order.address.addressLine2 ? `, ${order.address.addressLine2}` : ""
          }, ${order.address.city}, ${order.address.state} - ${
            order.address.pincode
          }`,
          totalAmount: parseFloat(order.totalAmount),
          items,
          deliveryTime: order.slot?.deliveryTime.toISOString() || null,
          status,
          isPackaged:
            order.orderItems.every((item) => item.is_packaged) || false,
          isDelivered: statusRecord?.isDelivered || false,
          isCod: order.isCod,
          paymentMode: order.isCod ? "COD" : "Online",
          paymentStatus: statusRecord?.paymentStatus || "pending",
          slotId: order.slotId,
          adminNotes: order.adminNotes,
          userNotes: order.userNotes,
        };
      });

      return { success: true, data: formattedOrders };
    }),

  updateAddressCoords: protectedProcedure
    .input(
      z.object({
        addressId: z.number(),
        latitude: z.number(),
        longitude: z.number(),
      })
    )
    .mutation(async ({ input }) => {
      const { addressId, latitude, longitude } = input;

      const result = await db
        .update(addresses)
        .set({
          adminLatitude: latitude,
          adminLongitude: longitude,
        })
        .where(eq(addresses.id, addressId))
        .returning();

      if (result.length === 0) {
        throw new ApiError("Address not found", 404);
      }

      return { success: true };
    }),

  getAll: protectedProcedure
    .input(getAllOrdersSchema)
    .query(async ({ input }) => {
      try {
        const {
          cursor,
          limit,
          slotId,
          packagedFilter,
          deliveredFilter,
          cancellationFilter,
          flashDeliveryFilter,
        } = input;

        let whereCondition: SQL<unknown> | undefined = eq(orders.id, orders.id); // always true
        if (cursor) {
          whereCondition = and(whereCondition, lt(orders.id, cursor));
        }
        if (slotId) {
          whereCondition = and(whereCondition, eq(orders.slotId, slotId));
        }
        if (packagedFilter === "packaged") {
          whereCondition = and(
            whereCondition,
            eq(orderStatus.isPackaged, true)
          );
        } else if (packagedFilter === "not_packaged") {
          whereCondition = and(
            whereCondition,
            eq(orderStatus.isPackaged, false)
          );
        }
        if (deliveredFilter === "delivered") {
          whereCondition = and(
            whereCondition,
            eq(orderStatus.isDelivered, true)
          );
        } else if (deliveredFilter === "not_delivered") {
          whereCondition = and(
            whereCondition,
            eq(orderStatus.isDelivered, false)
          );
        }
        if (cancellationFilter === "cancelled") {
          whereCondition = and(
            whereCondition,
            eq(orderStatus.isCancelled, true)
          );
        } else if (cancellationFilter === "not_cancelled") {
          whereCondition = and(
            whereCondition,
            eq(orderStatus.isCancelled, false)
          );
        }
        if (flashDeliveryFilter === "flash") {
          whereCondition = and(
            whereCondition,
            eq(orders.isFlashDelivery, true)
          );
        } else if (flashDeliveryFilter === "regular") {
          whereCondition = and(
            whereCondition,
            eq(orders.isFlashDelivery, false)
          );
        }

        const allOrders = await db.query.orders.findMany({
          where: whereCondition,
          orderBy: desc(orders.createdAt),
          limit: limit + 1, // fetch one extra to check if there's more
          with: {
            user: true,
            address: true,
            slot: true,
            orderItems: {
              with: {
                product: {
                  with: {
                    unit: true,
                  },
                },
              },
            },
            orderStatus: true,
          },
        });

        const hasMore = allOrders.length > limit;
        const ordersToReturn = hasMore ? allOrders.slice(0, limit) : allOrders;

        const filteredOrders = ordersToReturn.filter((order) => {
          const statusRecord = order.orderStatus[0];
          return (
            order.isCod ||
            (statusRecord && statusRecord.paymentStatus === "success")
          );
        });

        const formattedOrders = filteredOrders.map((order) => {
          const statusRecord = order.orderStatus[0];
          let status: "pending" | "delivered" | "cancelled" = "pending";
          if (statusRecord?.isCancelled) {
            status = "cancelled";
          } else if (statusRecord?.isDelivered) {
            status = "delivered";
          }

          const items = order.orderItems
            .map((item) => ({
              id: item.id,
              name: item.product.name,
              quantity: parseFloat(item.quantity),
              price: parseFloat(item.price.toString()),
              amount:
                parseFloat(item.quantity) * parseFloat(item.price.toString()),
              unit: item.product.unit?.shortNotation || "",
              productSize: item.product.productQuantity,
              isPackaged: item.is_packaged,
              isPackageVerified: item.is_package_verified,
            }))
            .sort((first, second) => first.id - second.id);
           dayjs.extend(utc);
           return {
              id: order.id,
              orderId: order.id.toString(),
              readableId: order.id,
             customerName: order.user.name,
            address: `${order.address.addressLine1}${
              order.address.addressLine2
                ? `, ${order.address.addressLine2}`
                : ""
            }, ${order.address.city}, ${order.address.state} - ${
              order.address.pincode
            }, Phone: ${order.address.phone}`,
             addressId: order.addressId,
             latitude: order.address.adminLatitude ?? order.address.latitude,
             longitude: order.address.adminLongitude ?? order.address.longitude,
            totalAmount: parseFloat(order.totalAmount),
            deliveryCharge: parseFloat(order.deliveryCharge || "0"),
            items,
            createdAt: order.createdAt,
            //  deliveryTime: order.slot ? dayjs.utc(order.slot.deliveryTime).format('ddd, MMM D • h:mm A') : 'Not scheduled',
          deliveryTime: order.slot?.deliveryTime.toISOString() || null,
            status,
            isPackaged:
              order.orderItems.every((item) => item.is_packaged) || false,
            isDelivered: statusRecord?.isDelivered || false,
            isCod: order.isCod,
            isFlashDelivery: order.isFlashDelivery,
            userNotes: order.userNotes,
            adminNotes: order.adminNotes,
          };
        });
        
        return {
          orders: formattedOrders,
          nextCursor: hasMore
            ? ordersToReturn[ordersToReturn.length - 1].id
            : undefined,
        };
      } catch (e) {
        console.log({ e });
      }
    }),

  rebalanceSlots: protectedProcedure
    .input(z.object({ slotIds: z.array(z.number()).min(1).max(50) }))
    .mutation(async ({ input }) => {
      const slotIds = input.slotIds;

      const ordersList = await db.query.orders.findMany({
        where: inArray(orders.slotId, slotIds),
        with: {
          orderItems: {
            with: {
              product: true
            }
          },
          couponUsages: {
            with: {
              coupon: true
            }
          },
        }
      });

      const processedOrdersData = ordersList.map((order) => {

        let newTotal = order.orderItems.reduce((acc,item) => {
          const latestPrice = +item.product.price;
          const amount = (latestPrice * Number(item.quantity));
          return acc+amount;
        },0)

        order.orderItems.forEach(item => {
          item.price = item.product.price;
          item.discountedPrice = item.product.price
        })

        const coupon = order.couponUsages[0]?.coupon;

        let discount = 0;
        if(coupon && !coupon.isInvalidated && (!coupon.validTill || new Date(coupon.validTill) > new Date())) {
          const proportion = Number(order.orderGroupProportion || 1);
          if(coupon.discountPercent) {
            const maxDiscount = Number(coupon.maxValue || Infinity) * proportion;
            discount = Math.min((newTotal * parseFloat(coupon.discountPercent)) / 100, maxDiscount);
          }
          else {
            discount = Number(coupon.flatDiscount) * proportion;
          }
        }
        newTotal -= discount

        const { couponUsages, orderItems: orderItemsRaw, ...rest} = order;
        const updatedOrderItems = orderItemsRaw.map(item => {
          const { product, ...rawOrderItem } = item;
          return rawOrderItem;
        })
        return {order: rest, updatedOrderItems, newTotal }
      })

      const updatedOrderIds: number[] = [];
      await db.transaction(async (tx) => {
        for (const { order, updatedOrderItems, newTotal } of processedOrdersData) {
          await tx.update(orders).set({ totalAmount: newTotal.toString() }).where(eq(orders.id, order.id));
          updatedOrderIds.push(order.id);

          for (const item of updatedOrderItems) {
            await tx.update(orderItems).set({
              price: item.price,
              discountedPrice: item.discountedPrice
            }).where(eq(orderItems.id, item.id));
          }
        }
      });

      return { success: true, updatedOrders: updatedOrderIds, message: `Rebalanced ${updatedOrderIds.length} orders.` };
    }),

  cancelOrder: protectedProcedure
    .input(z.object({
      orderId: z.number(),
      reason: z.string().min(1, "Cancellation reason is required"),
    }))
    .mutation(async ({ input }) => {
      const { orderId, reason } = input;

      const order = await db.query.orders.findFirst({
        where: eq(orders.id, orderId),
        with: {
          orderStatus: true,
        },
      });

      if (!order) {
        throw new ApiError("Order not found", 404);
      }

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

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

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

      const result = await db.transaction(async (tx) => {
        await tx
          .update(orderStatus)
          .set({
            isCancelled: true,
            isCancelledByAdmin: true,
            cancelReason: reason,
            cancellationAdminNotes: reason,
            cancellationReviewed: true,
            cancellationReviewedAt: new Date(),
          })
          .where(eq(orderStatus.id, status.id));

        const refundStatus = order.isCod ? "na" : "pending";

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

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

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

      return { success: true, message: "Order cancelled successfully" };
    }),
});

// {"id": "order_Rhh00qJNdjUp8o", "notes": {"retry": "true", "customerOrderId": "14"}, "amount": 21000, "entity": "order", "status": "created", "receipt": "order_14_retry", "attempts": 0, "currency": "INR", "offer_id": null, "signature": "6df20655021f1d6841340f2a2ef2ef9378cb3d43495ab09e85f08aea1a851583", "amount_due": 21000, "created_at": 1763575791, "payment_id": "pay_Rhh15cLL28YM7j", "amount_paid": 0}

type RefundStatus = "success" | "pending" | "failed" | "none" | "na";
