import { z } from "zod";
import { createRouter, publicQuery, authedQuery, adminQuery } from "../middleware";
import { getDb } from "../queries/connection";
import { orders, orderItems, products } from "@db/schema";
import { eq, desc, sql } from "drizzle-orm";

export const orderRouter = createRouter({
  create: publicQuery
    .input(
      z.object({
        customerName: z.string().min(1),
        customerEmail: z.string().email(),
        customerPhone: z.string().optional(),
        items: z.array(
          z.object({
            productId: z.number(),
            quantity: z.number().min(1),
            unitPrice: z.number(),
          })
        ),
        totalAmount: z.number(),
        discountAmount: z.number().default(0),
        finalAmount: z.number(),
        checkoutMethod: z.enum(["whatsapp", "telegram", "website"]).default("whatsapp"),
        notes: z.string().optional(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      const db = getDb();
      
      // Generate order number
      const orderNum = "DST" + Date.now().toString(36).toUpperCase();
      
      const orderData: any = {
        orderNumber: orderNum,
        status: "pending",
        totalAmount: input.totalAmount.toString(),
        discountAmount: input.discountAmount.toString(),
        finalAmount: input.finalAmount.toString(),
        customerName: input.customerName,
        customerEmail: input.customerEmail,
        customerPhone: input.customerPhone || null,
        checkoutMethod: input.checkoutMethod,
        notes: input.notes || null,
      };
      
      if (ctx.user) {
        orderData.userId = ctx.user.id;
      }
      
      const result = await db.insert(orders).values(orderData);
      const orderId = Number(result[0].insertId);
      
      // Insert order items
      for (const item of input.items) {
        await db.insert(orderItems).values({
          orderId,
          productId: item.productId,
          quantity: item.quantity,
          unitPrice: item.unitPrice.toString(),
          totalPrice: (item.unitPrice * item.quantity).toString(),
        });
      }
      
      return { orderId, orderNumber: orderNum };
    }),

  myOrders: authedQuery.query(async ({ ctx }) => {
    const db = getDb();
    return db
      .select()
      .from(orders)
      .where(eq(orders.userId, ctx.user.id))
      .orderBy(desc(orders.createdAt));
  }),

  getByOrderNumber: publicQuery
    .input(z.object({ orderNumber: z.string() }))
    .query(async ({ input }) => {
      const db = getDb();
      const result = await db
        .select()
        .from(orders)
        .where(eq(orders.orderNumber, input.orderNumber))
        .limit(1);
      
      if (!result[0]) return null;
      
      const items = await db
        .select()
        .from(orderItems)
        .where(eq(orderItems.orderId, result[0].id));
      
      // Get product details
      const enrichedItems = [];
      for (const item of items) {
        const product = await db
          .select()
          .from(products)
          .where(eq(products.id, item.productId))
          .limit(1);
        enrichedItems.push({ ...item, product: product[0] || null });
      }
      
      return { ...result[0], items: enrichedItems };
    }),

  list: adminQuery
    .input(
      z.object({
        status: z.string().optional(),
        page: z.number().default(1),
        limit: z.number().default(20),
      }).optional()
    )
    .query(async ({ input }) => {
      const db = getDb();
      const { page = 1, limit = 20 } = input || {};
      const offset = (page - 1) * limit;
      
      const items = await db
        .select()
        .from(orders)
        .orderBy(desc(orders.createdAt))
        .limit(limit)
        .offset(offset);
      
      const countResult = await db
        .select({ count: sql<number>`count(*)` })
        .from(orders);
      
      return {
        orders: items,
        total: countResult[0]?.count || 0,
        page,
        limit,
      };
    }),

  updateStatus: adminQuery
    .input(
      z.object({
        id: z.number(),
        status: z.enum([
          "pending",
          "payment_pending",
          "payment_verified",
          "processing",
          "delivered",
          "cancelled",
          "refunded",
        ]),
      })
    )
    .mutation(async ({ input }) => {
      const db = getDb();
      await db
        .update(orders)
        .set({ status: input.status })
        .where(eq(orders.id, input.id));
      
      return { success: true };
    }),
});
