import React, { useState, useEffect, useMemo } from "react";
import {
  View,
  TouchableOpacity,
  Alert,
  ActivityIndicator,
  Linking,
} from "react-native";
import DraggableFlatList, {
  RenderItemParams,
  ScaleDecorator,
} from "react-native-draggable-flatlist";
import {
  AppContainer,
  MyText,
  tw,
  useManualRefresh,
  useMarkDataFetchers,
  BottomDialog,
  Checkbox,
  BottomDropdown,
} from "common-ui";
import { useQueryClient } from "@tanstack/react-query";
import dayjs from "dayjs";
import { useLocalSearchParams, useRouter } from "expo-router";
import { trpc } from "@/src/trpc-client";
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
import Entypo from "@expo/vector-icons/Entypo";
import * as Location from "expo-location";
import { OrderOptionsMenu } from "@/components/OrderOptionsMenu";
import CancelOrderDialog from "@/components/CancelOrderDialog";
import { OrderNotesForm } from "@/components/OrderNotesForm";

// Define types outside
interface OrderWithSequence {
  sequenceId: number;
  readableId: number;
  isPackaged: boolean;
  totalAmount: number;
  address: string;
  latitude: number | null;
  longitude: number | null;
  id: number;
  isDelivered: boolean;
  addressId: number;
  adminNotes?: string | null;
  customerName?: string | null;
  assignedUserName?: string | null;
}

interface SlotProgressProps {
  slotId: number;
  orders: any[];
}

const SlotProgress: React.FC<SlotProgressProps> = ({ slotId, orders }) => {
  const delivered = orders.filter((o) => o.isDelivered).length;
  const undelivered = orders.filter((o) => !o.isDelivered).length;
  const packaged = orders.filter((o) => o.isPackaged).length;
  const notPackaged = orders.filter((o) => !o.isPackaged).length;

  const stats = [
    { label: "Delivered", value: delivered },
    { label: "Undelivered", value: undelivered },
    { label: "Packaged", value: packaged },
    { label: "Not Packaged", value: notPackaged },
  ];

  return (
    <View style={tw`bg-white px-4 py-3 border-b border-gray-200 mb-2`}>
      <MyText style={tw`text-gray-700 text-sm mb-3`}>
        Slot {slotId} Statistics
      </MyText>
      <View style={tw`flex-row flex-wrap`}>
        {stats.map((stat, index) => (
          <View key={index} style={tw`w-1/2 p-2`}>
            <View style={tw`bg-gray-50 p-3 rounded-lg border border-gray-200`}>
              <MyText style={tw`text-gray-900 font-bold text-lg`}>
                {stat.value}
              </MyText>
              <MyText style={tw`text-gray-500 text-xs`}>{stat.label}</MyText>
            </View>
          </View>
        ))}
      </View>
    </View>
  );
};

interface OrderItemProps {
  item: OrderWithSequence;
  drag: () => void;
  isActive: boolean;
  isPending: boolean;
  setSelectedOrder: (order: OrderWithSequence | null) => void;
  setShowOrderMenu: (show: boolean) => void;
  selectedOrderIds: number[];
  onToggleOrder: (id: number) => void;
  assignedUserName?: string | null;
  staffData?: { staff?: Array<{ id: number; name: string }> };
  setSelectedUserId?: (id: number) => void;
}

const OrderItem: React.FC<OrderItemProps> = ({
  item,
  drag,
  isActive,
  isPending,
  setSelectedOrder,
  setShowOrderMenu,
  selectedOrderIds,
  onToggleOrder,
  assignedUserName,
  staffData,
  setSelectedUserId,
}) => {
  const orderItem = item;

  return (
    <ScaleDecorator>
      <TouchableOpacity
        onLongPress={drag}
        disabled={isPending}
        activeOpacity={1}
        style={tw`mx-4 my-2`}
      >
        <View
          style={[
            tw`bg-white p-4 rounded-xl border`,
            isActive
              ? tw`shadow-xl border-blue-500 z-50`
              : tw`shadow-sm border-gray-100`,
          ]}
        >
          <View style={tw`flex-row items-center`}>
            {/* Checkbox and Drag Handle */}
            <View style={tw`mr-4 flex-col items-center`}>
              <Checkbox
                checked={selectedOrderIds.includes(orderItem.id)}
                onPress={() => onToggleOrder(orderItem.id)}
                size={20}
                fillColor="#3b82f6"
                checkColor="#FFFFFF"
              />
              <View style={tw`mt-1`}>
                <MaterialIcons
                  name="drag-indicator"
                  size={24}
                  color={isActive ? "#3b82f6" : "#9ca3af"}
                />
              </View>
            </View>

            {/* Content */}
            <View style={tw`flex-1`}>
              <View style={tw`flex-row justify-between items-start mb-2`}>
                <View style={tw`flex-row items-center gap-2`}>
                  <MyText style={tw`font-bold text-gray-800 text-lg`}>
                    #{orderItem.readableId}
                  </MyText>
                  <View style={tw`flex-row items-center gap-1`}>
                    <MyText style={tw`text-xs font-medium text-gray-600`}>
                      Pkg
                    </MyText>
                    <Checkbox
                      checked={orderItem.isPackaged}
                      size={16}
                      fillColor="#6B7280"
                      checkColor="#FFFFFF"
                    />
                  </View>
                  {/* Optional: Add time if available, or just keep ID */}
                </View>
                <View style={tw`flex-row items-center`}>
                  <View
                    style={tw`bg-green-50 px-2 py-1 rounded-lg border border-green-100 mr-2`}
                  >
                    <MyText style={tw`font-bold text-green-700 text-sm`}>
                      ₹{orderItem.totalAmount}
                    </MyText>
                  </View>
                  <TouchableOpacity
                    onPress={() => {
                      setSelectedOrder(orderItem);
                      setShowOrderMenu(true);
                    }}
                    style={tw`p-2`}
                  >
                    <Entypo
                      name="dots-three-vertical"
                      size={20}
                      color="#6b7280"
                    />
                  </TouchableOpacity>
                </View>
              </View>

              <View style={tw`flex-row items-start`}>
                <MaterialIcons
                  name="location-on"
                  size={14}
                  color="#6b7280"
                  style={tw`mr-1 mt-0.5`}
                />
                <MyText
                  style={tw`text-gray-500 text-xs flex-1`}
                  numberOfLines={2}
                >
                  {orderItem.address}
                </MyText>
                {orderItem.latitude && orderItem.longitude && (
                  <TouchableOpacity
                    onPress={() => {
                      Linking.openURL(
                        `https://www.google.com/maps?q=${orderItem.latitude},${orderItem.longitude}`
                      );
                    }}
                    style={tw`ml-2`}
                  >
                    <MaterialIcons name="map" size={16} color="#3b82f6" />
                  </TouchableOpacity>
                )}
              </View>
              {assignedUserName && (
                <View style={tw`mt-2 flex-row items-center`}>
                  <MyText style={tw`text-xs text-gray-500`}>
                    Assigned to{" "}
                  </MyText>
                  <TouchableOpacity
                    onPress={() => {
                      const assignedUserId = staffData?.staff?.find(
                        (s: { id: number; name: string }) => s.name === assignedUserName
                      )?.id;
                      if (assignedUserId && setSelectedUserId) {
                        setSelectedUserId(assignedUserId);
                      }
                    }}
                  >
                    <MyText style={tw`text-xs text-blue-600 underline`}>
                      {assignedUserName}
                    </MyText>
                  </TouchableOpacity>
                </View>
              )}
            </View>
          </View>
          {/* Admin Notes */}
          {orderItem.adminNotes && (
            <View
              style={tw`bg-yellow-50 p-2 rounded-lg border border-yellow-100 mt-2`}
            >
              <MyText style={tw`text-xs text-yellow-900 leading-4`}>
                {orderItem.adminNotes}
              </MyText>
            </View>
          )}
        </View>
      </TouchableOpacity>
    </ScaleDecorator>
  );
};

export default function DeliverySequences() {
  const { slotId } = useLocalSearchParams();
  const selectedSlotId = slotId ? Number(slotId) : null;
  const [localOrderedOrders, setLocalOrderedOrders] = useState<
    OrderWithSequence[]
  >([]);
  const [showOrderMenu, setShowOrderMenu] = useState(false);
  const [selectedOrder, setSelectedOrder] = useState<OrderWithSequence | null>(
    null
  );
  const [selectedUserId, setSelectedUserId] = useState<number>(-1);
  const [selectedOrderIds, setSelectedOrderIds] = useState<number[]>([]);
  const [hasSequenceChanged, setHasSequenceChanged] = useState(false);
  const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
  const [notesDialogOpen, setNotesDialogOpen] = useState(false);
  const router = useRouter();

  const { data: slotsData, refetch: refetchSlots } =
    trpc.admin.slots.getAll.useQuery();
  const {
    data: ordersData,
    isLoading: ordersLoading,
    refetch: refetchOrders,
  } = trpc.admin.order.getSlotOrders.useQuery(
    { slotId: String(selectedSlotId) },
    {
      enabled: !!selectedSlotId,
    }
  );
  const { data: sequenceData, refetch: refetchSequence } =
  trpc.admin.slots.getDeliverySequence.useQuery(
    { id: String(selectedSlotId) },
    {
      enabled: !!selectedSlotId,
    }
  );
  
  const { data: staffData } = trpc.admin.staffUser.getStaff.useQuery();

  // Auto-select first slot if no slotId provided
  useEffect(() => {
    if (!slotId && slotsData?.slots && slotsData.slots.length > 0) {
      router.replace(`/manage-orders/delivery-sequences?slotId=${slotsData.slots[0].id}`);
    }
  }, [slotId, slotsData, router]);

  const updateSequenceMutation =
    trpc.admin.slots.updateDeliverySequence.useMutation();
  const updatePackagedMutation = trpc.admin.order.updatePackaged.useMutation();
  const updateDeliveredMutation =
    trpc.admin.order.updateDelivered.useMutation();
  const updateAddressCoordsMutation =
    trpc.admin.order.updateAddressCoords.useMutation();

  // Manual refresh functionality
  useManualRefresh(() => {
    refetchSlots();
    refetchOrders();
    refetchSequence();
  });

  useMarkDataFetchers(() => {
    refetchSlots();
    refetchOrders();
    refetchSequence();
  });

  const slots = slotsData?.slots || [];
  const orders = ordersData?.data || [];
  const deliverySequence = sequenceData?.deliverySequence || [];

  const slotOptions =
    slots?.map((slot) => ({
      label: dayjs(slot.deliveryTime).format("ddd DD MMM, h:mm a"),
      value: slot.id,
    })) || [];

  const userOptions = [
    { label: "Unassigned", value: -1 },
    { label: "All Users", value: -2 },
    ...(staffData?.staff?.map((staff) => ({
      label: staff.name,
      value: staff.id,
    })) || []),
  ];

  // Create ordered orders based on delivery sequence
  const computedOrderedOrders = useMemo(() => {
    if (orders.length > 0) {
      const userSequence =
        selectedUserId !== -1
          ? (deliverySequence as any)?.[String(selectedUserId)] || []
          : null;
      if (selectedUserId !== -1 && userSequence && userSequence.length > 0) {
        // Sort orders according to user's sequence
        const sequenceMap = new Map(
          userSequence.map((id: number, index: number) => [id, index])
        );
        let ordered = orders
          .filter((order) => userSequence.includes(order.id))
          .map((order) => ({ ...order, sequenceId: order.id }))
          .sort((a, b) => {
            const aIndex = sequenceMap.get(a.sequenceId) ?? Infinity;
            const bIndex = sequenceMap.get(b.sequenceId) ?? Infinity;
            return aIndex < bIndex ? -1 : aIndex > bIndex ? 1 : 0;
          });
        return ordered;
      } else if (selectedUserId === -1) {
        // Show unassigned orders (not in any user's sequence)
        const assignedIds = new Set(
          Object.values(deliverySequence as any).flat()
        );
        let ordered = orders
          .filter((order) => !assignedIds.has(order.id))
          .map((order) => ({ ...order, sequenceId: order.id }))
          .sort((a, b) =>
            a.sequenceId < b.sequenceId
              ? -1
              : a.sequenceId > b.sequenceId
              ? 1
              : 0
          );
        return ordered;
      } else if (selectedUserId === -2) {
        // Show all orders with assignment info
        const orderToUserMap = new Map<number, number>();
        Object.entries(deliverySequence as any).forEach(([userId, orderIds]) => {
          (orderIds as number[]).forEach((orderId) => {
            orderToUserMap.set(orderId, parseInt(userId));
          });
        });
        let ordered = orders
          .map((order) => {
            const assignedUserId = orderToUserMap.get(order.id);
            const assignedUser = staffData?.staff?.find(
              (s) => s.id === assignedUserId
            );
            return {
              ...order,
              sequenceId: order.id,
              assignedUserName: assignedUser?.name || null,
            };
          })
          .sort((a, b) =>
            a.sequenceId < b.sequenceId
              ? -1
              : a.sequenceId > b.sequenceId
              ? 1
              : 0
          );
        return ordered;
      } else {
        // No sequence for user, show empty
        return [];
      }
    } else {
      return [];
    }
  }, [ordersData, sequenceData, selectedUserId]);

  // Sync local state with computed orders
  useEffect(() => {
    setLocalOrderedOrders(computedOrderedOrders);
  }, [computedOrderedOrders]);

  const handleDragEnd = ({ data }: { data: OrderWithSequence[] }) => {
    if (selectedUserId !== -1 && selectedUserId !== -2) {
      setLocalOrderedOrders(data);
      setHasSequenceChanged(true);
    }
  };

  const handleSaveSequence = () => {
    if (!selectedSlotId || selectedUserId === -1) return;

    const newSequence = { ...(deliverySequence as any) };
    newSequence[String(selectedUserId)] = localOrderedOrders.map(
      (order) => order.sequenceId
    );

    updateSequenceMutation.mutate(
      {
        id: selectedSlotId,
        deliverySequence: newSequence,
      },
      {
        onSuccess: () => {
          setHasSequenceChanged(false);
          Alert.alert("Success", "Delivery sequence updated successfully");
        },
        onError: (error: any) => {
          Alert.alert(
            "Error",
            `Failed to update delivery sequence: ${
              error.message || "Unknown error"
            }`
          );
        },
      }
    );
  };

  if (!slotsData) {
    return (
      <View style={tw`flex-1 justify-center items-center bg-gray-50 pt-6`}>
        <ActivityIndicator size="large" color="#3b82f6" />
        <MyText style={tw`text-gray-500 mt-4`}>Loading slots...</MyText>
      </View>
    );
  }

  if (slotsData.slots.length === 0) {
    return (
      <View style={tw`flex-1 justify-center items-center p-8 pt-6`}>
        <MaterialIcons name="event-busy" size={64} color="#e5e7eb" />
        <MyText style={tw`text-gray-500 mt-4 text-center text-lg`}>
          No slots available
        </MyText>
      </View>
    );
  }

  return (
    <View style={tw`flex-1 bg-gray-50 pt-6`}>
      {selectedSlotId ? (
        <>
          {/* Header Section */}
          <View
            style={tw`bg-white px-4 py-4 border-b border-gray-200 flex-row items-center shadow-sm z-10`}
          >
            <TouchableOpacity
              onPress={() => router.back()}
              style={tw`p-2 -ml-4`}
              accessibilityLabel="Go back"
            >
              <MaterialIcons name="chevron-left" size={24} color="#374151" />
            </TouchableOpacity>

            <View style={tw`flex-2 mx-2`}>
              <BottomDropdown
                label="Select Slot"
                options={slotOptions}
                value={selectedSlotId || ""}
                onValueChange={(val) => {
                  if (val) {
                    router.replace(`/manage-orders/delivery-sequences?slotId=${val}`);
                  }
                }}
                placeholder="Select slot"
              />
            </View>
            <View style={tw`flex-1 mx-2`}>
              <BottomDropdown
                label="Select User"
                options={userOptions}
                value={selectedUserId}
                onValueChange={(val) => setSelectedUserId(val as number)}
                placeholder="Select user"
              />
            </View>
          </View>

          {/* Content Section */}
          {ordersLoading ? (
            <View style={tw`flex-1 justify-center items-center`}>
              <ActivityIndicator size="large" color="#3b82f6" />
              <MyText style={tw`text-gray-500 mt-4`}>Loading orders...</MyText>
            </View>
          ) : localOrderedOrders.length === 0 ? (
            <View style={tw`flex-1 justify-center items-center p-8`}>
              <MaterialIcons name="assignment-late" size={64} color="#e5e7eb" />
              <MyText style={tw`text-gray-500 mt-4 text-center text-lg`}>
                No orders found for this slot
              </MyText>
            </View>
          ) : (
            <View style={tw`flex-1`}>
              {/* <View style={tw`bg-blue-50 px-4 py-2 mb-2`}>
                 <MyText style={tw`text-blue-700 text-xs text-center`}>
                   Long press an item to drag and reorder
                 </MyText>
                 </View> */}
                <DraggableFlatList
                data={localOrderedOrders}
                renderItem={({ item, drag, isActive }) => (
                  <OrderItem
                    item={item}
                    drag={drag}
                    isActive={isActive}
                    isPending={updateSequenceMutation.isPending}
                    setSelectedOrder={setSelectedOrder}
                    setShowOrderMenu={setShowOrderMenu}
                    selectedOrderIds={selectedOrderIds}
                    onToggleOrder={(id) => {
                      setSelectedOrderIds((prev) =>
                        prev.includes(id)
                          ? prev.filter((i) => i !== id)
                          : [...prev, id]
                      );
                    }}
                    assignedUserName={selectedUserId === -2 ? item.assignedUserName : undefined}
                    staffData={staffData}
                    setSelectedUserId={setSelectedUserId}
                  />
                )}
                keyExtractor={(item) => item.sequenceId.toString()}
                onDragEnd={handleDragEnd}
                showsVerticalScrollIndicator={false}
                contentContainerStyle={tw`pb-8`}
                ListHeaderComponent={
                  <SlotProgress slotId={selectedSlotId!} orders={orders} />
                }
              />
            </View>
          )}

          {/* FAB for Assignment */}
          {selectedOrderIds.length > 0 && (
            <View style={tw`absolute bottom-4 right-4`}>
              <BottomDropdown
                label="Assign To"
                options={[
                  ...userOptions.filter((opt) => opt.value !== -1),
                  { label: "None", value: -3 },
                ]}
                value={-1}
                 onValueChange={(val) => {
                   if (val !== -1) {
                     if (val === -3) {
                       // Unassign selected orders
                      const newSequence = { ...(deliverySequence as any) };
                      Object.keys(newSequence).forEach((userId) => {
                        newSequence[userId] = newSequence[userId].filter(
                          (id: number) => !selectedOrderIds.includes(id)
                        );
                      });
                      // Save
                      updateSequenceMutation.mutate(
                        {
                          id: selectedSlotId,
                          deliverySequence: newSequence,
                        },
                        {
                          onSuccess: () => {
                            setSelectedOrderIds([]);
                            refetchSequence();
                            Alert.alert(
                              "Success",
                              "Orders unassigned successfully"
                            );
                          },
                          onError: (error: any) => {
                            Alert.alert(
                              "Error",
                              `Failed to unassign orders: ${
                                error.message || "Unknown error"
                              }`
                            );
                          },
                        }
                      );
                    } else {
                      // Assign selected orders to the user
                      // Update deliverySequence map
                      const newSequence = { ...(deliverySequence as any) };
                      // Remove from all other users
                      Object.keys(newSequence).forEach((userId) => {
                        newSequence[userId] = newSequence[userId].filter(
                          (id: number) => !selectedOrderIds.includes(id)
                        );
                      });
                      // Add to selected user
                      if (!newSequence[String(val)])
                        newSequence[String(val)] = [];
                      newSequence[String(val)] = [
                        ...new Set([
                          ...newSequence[String(val)],
                          ...selectedOrderIds,
                        ]),
                      ];
                      // Save
                      updateSequenceMutation.mutate(
                        {
                          id: selectedSlotId,
                          deliverySequence: newSequence,
                        },
                        {
                          onSuccess: () => {
                            setSelectedOrderIds([]);
                            refetchSequence();
                            Alert.alert(
                              "Success",
                              "Orders assigned successfully"
                            );
                          },
                          onError: (error: any) => {
                            Alert.alert(
                              "Error",
                              `Failed to assign orders: ${
                                error.message || "Unknown error"
                              }`
                            );
                          },
                        }
                      );
                    }
                  }
                }}
                triggerComponent={({ onPress }) => (
                  <TouchableOpacity
                    onPress={onPress}
                    style={tw`bg-blue-600 p-4 rounded-full shadow-lg`}
                  >
                    <MaterialIcons name="person-add" size={24} color="white" />
                  </TouchableOpacity>
                )}
              />
            </View>
          )}

          {/* FAB for Save */}
          {hasSequenceChanged && (
            <View style={tw`absolute bottom-4 left-4`}>
              <TouchableOpacity
                onPress={handleSaveSequence}
                style={tw`bg-blue-600 p-4 rounded-full shadow-lg`}
                disabled={updateSequenceMutation.isPending}
                accessibilityLabel="Save sequence"
              >
                <MaterialIcons name="save" size={24} color="white" />
              </TouchableOpacity>
            </View>
          )}
        </>
      ) : (
        <View style={tw`flex-1 justify-center items-center p-8`}>
          <MaterialIcons name="event-busy" size={64} color="#e5e7eb" />
          <MyText style={tw`text-gray-500 mt-4 text-center text-lg`}>
            No slot selected. Please select a slot to view delivery sequence.
          </MyText>
          <TouchableOpacity
            style={tw`mt-6 bg-blue-600 px-6 py-3 rounded-full`}
            onPress={() => router.back()}
          >
            <MyText style={tw`text-white font-bold`}>Go Back</MyText>
          </TouchableOpacity>
        </View>
      )}

      {/* Order Menu Dialog */}
      <OrderOptionsMenu
        open={showOrderMenu}
        onClose={() => setShowOrderMenu(false)}
        order={{
          id: selectedOrder?.id || 0,
          readableId: selectedOrder?.readableId || 0,
          isPackaged: selectedOrder?.isPackaged || false,
          isDelivered: selectedOrder?.isDelivered || false,
          address: selectedOrder?.address || '',
          addressId: selectedOrder?.addressId || 0,
          adminNotes: selectedOrder?.adminNotes || null,
          latitude: selectedOrder?.latitude || null,
          longitude: selectedOrder?.longitude || null,
        }}
        onViewDetails={() => {
          if (selectedOrder) {
            router.push(`/manage-orders/order-details/${selectedOrder.id}`);
          }
          setShowOrderMenu(false);
        }}
        onTogglePackaged={() => {
          if (!selectedOrder) return;
          updatePackagedMutation.mutate(
            { orderId: selectedOrder.id.toString(), isPackaged: !selectedOrder.isPackaged },
            {
              onSuccess: () => {
                refetchOrders();
                refetchSequence();
              },
              onError: () => {
                Alert.alert("Error", "Failed to update packaged status");
              },
            }
          );
        }}
        onToggleDelivered={() => {
          if (!selectedOrder) return;
          updateDeliveredMutation.mutate(
            { orderId: selectedOrder.id.toString(), isDelivered: !selectedOrder.isDelivered },
            {
              onSuccess: () => {
                refetchOrders();
                refetchSequence();
              },
              onError: () => {
                Alert.alert("Error", "Failed to update delivered status");
              },
            }
          );
        }}
        onOpenAdminNotes={() => {
          setShowOrderMenu(false);
          setNotesDialogOpen(true);
        }}
        onCancelOrder={() => {
          setShowOrderMenu(false);
          setCancelDialogOpen(true);
        }}
        onAttachLocation={() => {}}
        onWhatsApp={() => {}}
        onDial={() => {}}
      />

      <CancelOrderDialog
        orderId={selectedOrder?.id || 0}
        open={cancelDialogOpen}
        onClose={() => setCancelDialogOpen(false)}
        onSuccess={() => {
          refetchOrders();
          refetchSequence();
        }}
      />

      <BottomDialog open={notesDialogOpen} onClose={() => setNotesDialogOpen(false)}>
        <OrderNotesForm
          orderId={selectedOrder?.id || 0}
          initialNotes={selectedOrder?.adminNotes || ''}
          onSuccess={() => {
            refetchOrders();
            refetchSequence();
            setNotesDialogOpen(false);
          }}
          onCancel={() => setNotesDialogOpen(false)}
        />
      </BottomDialog>
    </View>
  );
}
