import { db } from '@/src/db/db_index'
import { orders, orderStatus } from '@/src/db/schema'
import redisClient from '@/src/lib/redis-client'
import { sendTelegramMessage } from '@/src/lib/telegram-service'
import { inArray, eq } from 'drizzle-orm';

const ORDER_CHANNEL = 'orders:placed';
const CANCELLED_CHANNEL = 'orders:cancelled';

interface OrderIdMessage {
  orderIds: number[];
}

interface CancellationMessage {
  orderId: number;
  cancelledBy: 'user' | 'admin';
  reason: string;
  cancelledAt: string;
}

const formatDateTime = (dateStr: string | null | undefined): string => {
  if (!dateStr) return 'N/A';
  return new Date(dateStr).toLocaleString('en-IN', {
    dateStyle: 'medium',
    timeStyle: 'short',
    timeZone: 'Asia/Kolkata',
  });
};

const formatOrderMessageWithFullData = (ordersData: any[]): string => {
  let message = '🛒 <b>New Order Placed</b>\n\n';

  ordersData.forEach((order, index) => {
    message += `<b>Order ${order.id}</b>\n`;

    message += '📦 <b>Items:</b>\n';
    order.orderItems?.forEach((item: any) => {
      message += `  • ${item.product?.name || 'Unknown'} x${item.quantity}\n`;
    });

    message += `\n💰 <b>Total:</b> ₹${order.totalAmount}\n`;

    message += `🚚 <b>Delivery:</b> ${
      order.isFlashDelivery ? 'Flash Delivery' : formatDateTime(order.slot?.deliveryTime)
    }\n`;

    message += `\n📍 <b>Address:</b>\n`;
    message += `  ${order.address?.name || 'N/A'}\n`;
    message += `  ${order.address?.addressLine1 || ''}\n`;
    if (order.address?.addressLine2) {
      message += `  ${order.address.addressLine2}\n`;
    }
    message += `  ${order.address?.city || ''}, ${order.address?.state || ''} - ${order.address?.pincode || ''}\n`;
    if (order.address?.phone) {
      message += `  📞 ${order.address.phone}\n`;
    }

    if (index < ordersData.length - 1) {
      message += '\n---\n\n';
    }
  });

  return message;
};

const formatCancellationMessage = (orderData: any, cancellationData: CancellationMessage): string => {
  const message = `❌ <b>Order Cancelled</b>

<b>Order #${orderData.id}</b>

👤 <b>Name:</b> ${orderData.address?.name || 'N/A'}
📞 <b>Phone:</b> ${orderData.address?.phone || 'N/A'}

📦 <b>Items:</b>
${orderData.orderItems?.map((item: any) => `  • ${item.product?.name || 'Unknown'} x${item.quantity}`).join('\n') || '  N/A'}

💰 <b>Total:</b> ₹${orderData.totalAmount}
💳 <b>Refund:</b> ${orderData.refundStatus === 'na' ? 'N/A (COD)' : orderData.refundStatus || 'Pending'}

❓ <b>Reason:</b> ${cancellationData.reason}
👤 <b>Cancelled by:</b> ${cancellationData.cancelledBy === 'admin' ? 'Admin' : 'User'}
⏰ <b>Time:</b> ${formatDateTime(cancellationData.cancelledAt)}
`;

  return message;
};

/**
 * Start the post order handler
 * Subscribes to the orders:placed channel and sends to Telegram
 */
export const startOrderHandler = async (): Promise<void> => {
  try {
    console.log('Starting post order handler...');

    await redisClient.subscribe(ORDER_CHANNEL, async (message: string) => {
      try {
        const { orderIds }: OrderIdMessage = JSON.parse(message);
        console.log('New order received, sending to Telegram...');

        const ordersData = await db.query.orders.findMany({
          where: inArray(orders.id, orderIds),
          with: {
            address: true,
            orderItems: { with: { product: true } },
            slot: true,
          },
        });

        const telegramMessage = formatOrderMessageWithFullData(ordersData);
        await sendTelegramMessage(telegramMessage);
      } catch (error) {
        console.error('Failed to process order message:', error);
        await sendTelegramMessage(`⚠️ Error parsing order: ${message}`);
      }
    });

    console.log('Post order handler started successfully');
  } catch (error) {
    console.error('Failed to start post order handler:', error);
    throw error;
  }
};

/**
 * Stop the post order handler
 */
export const stopOrderHandler = async (): Promise<void> => {
  try {
    await redisClient.unsubscribe(ORDER_CHANNEL);
    console.log('Post order handler stopped');
  } catch (error) {
    console.error('Error stopping post order handler:', error);
  }
};

export const startCancellationHandler = async (): Promise<void> => {
  try {
    console.log('Starting cancellation handler...');

    await redisClient.subscribe(CANCELLED_CHANNEL, async (message: string) => {
      try {
        const cancellationData: CancellationMessage = JSON.parse(message);
        console.log('Order cancellation received, sending to Telegram...');

        const orderData = await db.query.orders.findFirst({
          where: eq(orders.id, cancellationData.orderId),
          with: {
            address: true,
            orderItems: { with: { product: true } },
            refunds: true,
          },
        });

        if (!orderData) {
          console.error('Order not found for cancellation:', cancellationData.orderId);
          await sendTelegramMessage(`⚠️ Order ${cancellationData.orderId} was cancelled but could not be found in database`);
          return;
        }

        const refundStatus = orderData.refunds?.[0]?.refundStatus || 'pending';

        const telegramMessage = formatCancellationMessage({ ...orderData, refundStatus }, cancellationData);
        await sendTelegramMessage(telegramMessage);
      } catch (error) {
        console.error('Failed to process cancellation message:', error);
        await sendTelegramMessage(`⚠️ Error processing cancellation: ${message}`);
      }
    });

    console.log('Cancellation handler started successfully');
  } catch (error) {
    console.error('Failed to start cancellation handler:', error);
    throw error;
  }
};

export const stopCancellationHandler = async (): Promise<void> => {
  try {
    await redisClient.unsubscribe(CANCELLED_CHANNEL);
    console.log('Cancellation handler stopped');
  } catch (error) {
    console.error('Error stopping cancellation handler:', error);
  }
};

export const publishOrder = async (orderDetails: OrderIdMessage): Promise<boolean> => {
  try {
    const message = JSON.stringify(orderDetails);
    await redisClient.publish(ORDER_CHANNEL, message);
    return true;
  } catch (error) {
    console.error('Failed to publish order:', error);
    return false;
  }
};

export const publishFormattedOrder = async (
  createdOrders: any[],
  ordersBySlot: Map<number | null, any[]>
): Promise<boolean> => {
  try {
    const orderIds = createdOrders.map(order => order.id);
    return await publishOrder({ orderIds });
  } catch (error) {
    console.error('Failed to format and publish order:', error);
    return false;
  }
};

export const publishCancellation = async (
  orderId: number,
  cancelledBy: 'user' | 'admin',
  reason: string
): Promise<boolean> => {
  try {
    const message: CancellationMessage = {
      orderId,
      cancelledBy,
      reason,
      cancelledAt: new Date().toISOString(),
    };
    await redisClient.publish(CANCELLED_CHANNEL, JSON.stringify(message));
    console.log('Cancellation published to Redis:', orderId);
    return true;
  } catch (error) {
    console.error('Failed to publish cancellation:', error);
    return false;
  }
};
