import React, { useState, useCallback, useMemo, memo } from "react";
import { View, Dimensions, Image, RefreshControl } from "react-native";
import { LinearGradient } from "expo-linear-gradient";
import { useRouter } from "expo-router";
import {
  theme,
  tw,
  useManualRefresh,
  useMarkDataFetchers,
  LoadingDialog,
  MyTouchableOpacity,
  MyText, SearchBar, useStatusBarStore,
  colors
} from "common-ui";

import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
import ProductCard from "@/components/ProductCard";
import AddToCartDialog from "@/src/components/AddToCartDialog";
import MyFlatList from "common-ui/src/components/flat-list";

import { trpc } from "@/src/trpc-client";
import { useProductSlotIdentifier } from "@/hooks/useProductSlotIdentifier";
import FloatingCartBar from "@/components/floating-cart-bar";
import BannerCarousel from "@/components/BannerCarousel";
import { useUserDetails } from "@/src/contexts/AuthContext";
import TabLayoutWrapper from "@/components/TabLayoutWrapper";
import { useNavigationStore } from "@/src/store/navigationStore";
import { useGetEssentialConsts } from "@/src/api-hooks/essential-consts.api";
import NextOrderGlimpse from "@/components/NextOrderGlimpse";
dayjs.extend(relativeTime);

const { width: screenWidth } = Dimensions.get("window");
const itemWidth = screenWidth * 0.45;
const gridItemWidth = (screenWidth - 48) / 2;
const headerColor = colors.secondaryPink;

const formatTimeRange = (deliveryTime: string) => {
  const time = dayjs(deliveryTime);
  const endTime = time.add(1, 'hour');
  const startPeriod = time.format('A');
  const endPeriod = endTime.format('A');

  if (startPeriod === endPeriod) {
    return `${time.format('h')}-${endTime.format('h')} ${startPeriod}`;
  } else {
    return `${time.format('h:mm')} ${startPeriod} - ${endTime.format('h:mm')} ${endPeriod}`;
  }
};

const staticStyles = {
  flatListContent: { gap: 16 },
  columnWrapper: { gap: 16, paddingHorizontal: 16 },
  popularListContent: { paddingBottom: 16 },
  slotsListContent: { paddingBottom: 24 },
};

interface RenderStoreProps {
  item: any;
}

const RenderStore = memo(({ item }: RenderStoreProps) => {
  const router = useRouter();
  const { setNavigatedFromHome, setSelectedStoreId } = useNavigationStore();

  const handlePress = useCallback(() => {
    setNavigatedFromHome(true);
    setSelectedStoreId(item.id);
    router.push('/(drawer)/(tabs)/stores');
  }, [item.id, router, setNavigatedFromHome, setSelectedStoreId]);

  return (
    <MyTouchableOpacity
      style={tw`items-center mb-4`}
      onPress={handlePress}
      activeOpacity={0.7}
    >
      <View
        style={tw`w-16 h-16 rounded-2xl bg-white/20 border-2 border-white/30 items-center justify-center mb-2 shadow-lg overflow-hidden`}
      >
        {item.signedImageUrl ? (
          <Image source={{ uri: item.signedImageUrl }} style={tw`w-16 h-16 rounded-2xl`} resizeMode="cover" />
        ) : (
          <MaterialIcons name="storefront" size={28} color="#FFF" />
        )}
      </View>
      <MyText style={tw`font-bold text-xs text-center tracking-wide drop-shadow-sm text-neutral-800`} numberOfLines={1}>
        {item.name.replace(/^The\s+/i, "")}
      </MyText>
    </MyTouchableOpacity>
  );
});
RenderStore.displayName = 'RenderStore';

interface SlotCardProps {
  slot: any;
}

const SlotCard = memo(({ slot }: SlotCardProps) => {
  const router = useRouter();
  const now = dayjs();
  const freezeTime = dayjs(slot.freezeTime);
  const isClosingSoon = freezeTime.diff(now, "hour") < 4 && freezeTime.isAfter(now);

  const handlePress = useCallback(() => {
    router.push(`/(drawer)/(tabs)/home/slot-view?slotId=${slot.id}`);
  }, [router, slot.id]);

  return (
    <MyTouchableOpacity
      testID={`slot-card-${slot.id}`}
      style={[
        tw`bg-white rounded-[24px] p-5 mr-4 shadow-xl shadow-slate-200 border border-slate-100 min-w-[280px]`,
        isClosingSoon ? tw`border-l-4 border-l-amber-400` : tw`border-l-4 border-l-brand500`,
      ]}
      onPress={handlePress}
      activeOpacity={0.9}
    >
      <View style={tw`flex-row justify-end items-start mb-4`}>
        {isClosingSoon && (
          <View style={tw`bg-amber-50 px-2 py-0.5 rounded-md border border-amber-100 flex-row items-center`}>
            <View style={tw`w-1 h-1 rounded-full bg-amber-500 mr-1`} />
            <MyText style={tw`text-[10px] font-bold text-amber-700`}>CLOSING SOON</MyText>
          </View>
        )}
      </View>

      <View style={tw`flex-row justify-between mb-5`}>
        <View style={tw`flex-1 mr-4`}>
          <View style={tw`flex-row items-center mb-1.5`}>
            <View style={tw`bg-brand50 p-1 rounded-md mr-1.5`}>
              <MaterialIcons name="local-shipping" size={12} color={theme.colors.brand600} />
            </View>
            <MyText style={tw`text-[10px] font-bold text-brand700 uppercase`}>Delivery At</MyText>
          </View>
          <MyText style={tw`text-sm font-extrabold text-slate-900`}>{formatTimeRange(slot.deliveryTime)}</MyText>
          <MyText style={tw`text-[11px] font-bold text-slate-500`}>{dayjs(slot.deliveryTime).format("ddd, MMM DD")}</MyText>
        </View>

        <View style={tw`flex-1`}>
          <View style={tw`flex-row items-center mb-1.5`}>
            <View style={tw`bg-amber-50 p-1 rounded-md mr-1.5`}>
              <MaterialIcons name="timer" size={12} color="#D97706" />
            </View>
            <MyText style={tw`text-[10px] font-bold text-amber-700 uppercase`}>Order By</MyText>
          </View>
          <MyText style={tw`text-sm font-extrabold text-slate-900`}>{dayjs(slot.freezeTime).format("h:mm A")}</MyText>
          <MyText style={tw`text-[11px] font-bold text-slate-500`}>{dayjs(slot.freezeTime).format("ddd, MMM DD")}</MyText>
        </View>
      </View>

      <View style={tw`flex-row items-center`}>
        <View style={tw`flex-row mr-3`}>
          {slot.products.slice(0, 3).map((p: any, i: number) => (
            <View
              key={p.id}
              style={[tw`w-8 h-8 rounded-full border-2 border-white bg-slate-100 overflow-hidden`, i > 0 && tw`-ml-3`]}
            >
              {p.images?.[0] ? (
                <Image source={{ uri: p.images?.[0] }} style={tw`w-full h-full`} />
              ) : (
                <MaterialIcons name="image" size={14} color="#94A3B8" />
              )}
            </View>
          ))}
        </View>
        <MyText style={tw`text-[11px] font-bold text-brand600`}>View all {slot.products.length} items</MyText>
        <MaterialIcons name="chevron-right" size={16} color={theme.colors.brand600} />
      </View>
    </MyTouchableOpacity>
  );
});

interface PopularProductItemProps {
  item: any;
  onPress: (id: number) => void;
}

const PopularProductItem = memo(({ item, onPress }: PopularProductItemProps) => {
  const handlePress = useCallback(() => onPress(item.id), [item.id, onPress]);
  
  return (
    <View style={tw`mr-4`}>
      <ProductCard
        item={item}
        itemWidth={itemWidth}
        onPress={handlePress}
        showDeliveryInfo={false}
        useAddToCartDialog={true}
        miniView={true}
      />
    </View>
  );
});

interface SlotItemProps {
  item: any;
}

const SlotItem = memo(({ item }: SlotItemProps) => <SlotCard slot={item} />);

interface ProductItemProps {
  item: any;
  onPress: (id: number) => void;
}

const ProductItem = memo(({ item, onPress }: ProductItemProps) => {
  const handlePress = useCallback(() => onPress(item.id), [item.id, onPress]);
  
  return (
    <ProductCard
      item={item}
      itemWidth={gridItemWidth}
      onPress={handlePress}
      showDeliveryInfo={true}
      miniView={false}
      useAddToCartDialog={true}
    />
  );
});

interface ListHeaderProps {
  gradientHeight: number;
  onGradientLayout: (height: number) => void;
  storesData: any;
  popularProducts: any[];
  sortedSlots: any[];
  onProductPress: (id: number) => void;
}

const ListHeader = memo(({
  gradientHeight,
  onGradientLayout,
  storesData,
  popularProducts,
  sortedSlots,
  onProductPress,
}: ListHeaderProps) => {
  const handleLayout = useCallback((event: any) => {
    const { y, height } = event.nativeEvent.layout;
    onGradientLayout(y + height);
  }, [onGradientLayout]);

  const renderPopularItem = useCallback(({ item }: { item: any }) => (
    <PopularProductItem item={item} onPress={onProductPress} />
  ), [onProductPress]);

  const renderSlotItem = useCallback(({ item }: { item: any }) => (
    <SlotItem item={item} />
  ), []);

  const gradientStyle = useMemo(() => [
    tw`absolute left-0 right-0 shadow-lg`,
    { height: gradientHeight + 32, zIndex: -1 }
  ], [gradientHeight]);

  return (
    <>
      <View onLayout={handleLayout}>
        <LinearGradient
          colors={[headerColor, headerColor]}
          start={{ x: 0, y: 0 }}
          end={{ x: 1, y: 0.5 }}
          style={gradientStyle}
        />

        {storesData?.stores && storesData.stores.length > 0 && (
          <View style={tw`px-4 pb-2`}>
            <View style={tw`flex-row items-center justify-between mb-4 px-1`}>
              <View>
                <MyText style={tw`text-xl font-extrabold text-white tracking-tight drop-shadow-md text-neutral-800`}>
                  Our Stores
                </MyText>
                <MyText style={tw`text-xs font-medium mt-0.5 text-neutral-800`}>Fresh from our locations</MyText>
              </View>
            </View>
            <View style={tw`pb-2`}>
              <View style={tw`flex-row flex-wrap`}>
                {storesData.stores.map((store: any) => (
                  <View key={store.id} style={tw`w-1/4 p-1`}>
                    <RenderStore item={store} />
                  </View>
                ))}
              </View>
            </View>
          </View>
        )}
      </View>

      <View style={tw`py-4`}>
        <BannerCarousel />
      </View>

      <View style={tw`bg-white rounded-t-3xl px-4`}>
        <View style={tw`py-2`}>
          <NextOrderGlimpse />
        </View>

        <View style={tw`mb-4 pt-2 px-1`}>
          <MyText style={tw`text-2xl font-extrabold text-gray-900 tracking-tight`}>Popular Items</MyText>
          <MyText style={tw`text-sm text-gray-500 font-medium`}>Trending fresh picks just for you</MyText>
        </View>

        <View style={tw`relative`}>
          <MyFlatList
            data={popularProducts}
            keyExtractor={(item) => item.id.toString()}
            horizontal
            showsHorizontalScrollIndicator={false}
            contentContainerStyle={staticStyles.popularListContent}
            renderItem={renderPopularItem}
            removeClippedSubviews={true}
          />
          <LinearGradient
            colors={["transparent", "rgba(0,0,0,0.08)"]}
            start={{ x: 0, y: 0.5 }}
            end={{ x: 1, y: 0.5 }}
            style={tw`absolute right-0 top-0 bottom-4 w-12 rounded-l-xl`}
            pointerEvents="none"
          />
        </View>

        {sortedSlots.length > 0 && (
          <View style={tw`mt-2 mb-4`}>
            <View style={tw`flex-row items-center justify-between px-1 mb-6`}>
              <View>
                <MyText style={tw`text-2xl font-extrabold text-gray-900 tracking-tight`}>Upcoming Delivery Slots</MyText>
                <MyText style={tw`text-sm text-gray-500 font-medium mt-1`}>Plan your fresh deliveries ahead</MyText>
              </View>
            </View>
            <MyFlatList
              data={sortedSlots.slice(0, 5)}
              keyExtractor={(item) => item.id.toString()}
              horizontal
              showsHorizontalScrollIndicator={false}
              contentContainerStyle={staticStyles.slotsListContent}
              decelerationRate="fast"
              snapToInterval={280 + 16}
              renderItem={renderSlotItem}
              removeClippedSubviews={true}
            />
          </View>
        )}

        <View style={tw`mt-2 mb-4`}>
          <View style={tw`flex-row items-center justify-between px-1 mb-4`}>
            <View>
              <MyText style={tw`text-2xl font-extrabold text-gray-900 tracking-tight`}>All Available Products</MyText>
              <MyText style={tw`text-sm text-gray-500 font-medium mt-1`}>Browse our complete selection</MyText>
            </View>
          </View>
        </View>
      </View>
    </>
  );
});

export default function Dashboard() {
  const router = useRouter();
  const userDetails = useUserDetails();
  const [inputQuery, setInputQuery] = useState("");
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedTagId, setSelectedTagId] = useState<number | null>(null);
  const [isLoadingDialogOpen, setIsLoadingDialogOpen] = useState(false);
  const [gradientHeight, setGradientHeight] = useState(0);
  const [displayedProducts, setDisplayedProducts] = useState<any[]>([]);
  const [hasMore, setHasMore] = useState(true);
  const [isLoadingMore, setIsLoadingMore] = useState(false);
  const { backgroundColor } = useStatusBarStore();
  const { getQuickestSlot } = useProductSlotIdentifier();
  const [isRefreshing, setIsRefreshing] = useState(false);

  const {
    data: productsData,
    isLoading,
    error,
    refetch,
  } = trpc.common.product.getAllProductsSummary.useQuery({
    searchQuery: searchQuery || undefined,
    tagId: selectedTagId || undefined,
  });

  const { data: essentialConsts, isLoading: isLoadingConsts, error: constsError, refetch: refetchConsts } = useGetEssentialConsts();

  const { data: storesData, refetch: refetchStores } = trpc.user.stores.getStores.useQuery();
  const { data: slotsData, refetch: refetchSlots } = trpc.user.slots.getSlotsWithProducts.useQuery();

  const products = productsData?.products || [];

  React.useEffect(() => {
    if (products.length > 0 && displayedProducts.length === 0) {
      const initialBatch = products
        .filter(p => typeof p.id === "number")
        .sort((a, b) => {
          const slotA = getQuickestSlot(a.id);
          const slotB = getQuickestSlot(b.id);
          if (slotA && !slotB) return -1;
          if (!slotA && slotB) return 1;
          if (a.isOutOfStock && !b.isOutOfStock) return 1;
          if (!a.isOutOfStock && b.isOutOfStock) return -1;
          return 0;
        });

      setDisplayedProducts(initialBatch);
      setHasMore(products.length > 10);
    }
  }, [productsData]);

  const popularItemIds = useMemo(() => {
    const popularItems = essentialConsts?.popularItems;
    if (!popularItems) return [];

    if (Array.isArray(popularItems)) {
      return popularItems.map((id: any) => parseInt(id)).filter((id: number) => !isNaN(id));
    } else if (typeof popularItems === 'string') {
      return popularItems
        .split(',')
        .map((id: string) => parseInt(id.trim()))
        .filter((id: number) => !isNaN(id));
    }
    return [];
  }, [essentialConsts?.popularItems]);

  const sortedSlots = useMemo(() => {
    if (!slotsData?.slots) return [];
    return [...slotsData.slots].sort((a, b) => {
      const deliveryDiff = dayjs(a.deliveryTime).diff(dayjs(b.deliveryTime));
      if (deliveryDiff !== 0) return deliveryDiff;
      return dayjs(a.freezeTime).diff(dayjs(b.freezeTime));
    });
  }, [slotsData]);

  const popularProducts = useMemo(() => {
    return popularItemIds
      .map(id => products.find(product => product.id === id))
      .filter((product): product is NonNullable<typeof product> => product != null);
  }, [popularItemIds, products]);

  const handleRefresh = useCallback(async () => {
    setIsRefreshing(true);
    try {
      await Promise.all([refetch(), refetchStores(), refetchSlots(), refetchConsts()]);
    } finally {
      setIsRefreshing(false);
    }
  }, [refetch, refetchStores, refetchSlots, refetchConsts]);

  useManualRefresh(() => {
    handleRefresh();
  });

  useMarkDataFetchers(() => {
    handleRefresh();
  });

  const handleProductPress = useCallback((id: number) => {
    router.push(`/(drawer)/(tabs)/home/product-detail/${id}`);
  }, [router]);

  const handleGradientLayout = useCallback((height: number) => {
    setGradientHeight(height);
  }, []);

  const handleSearchPress = useCallback(() => {
    router.push("/(drawer)/(tabs)/home/search-results");
  }, [router]);

  const renderProductItem = useCallback(({ item }: { item: any }) => (
    <ProductItem item={item} onPress={handleProductPress} />
  ), [handleProductPress]);

  const listHeader = useMemo(() => (
    <ListHeader
      gradientHeight={gradientHeight}
      onGradientLayout={handleGradientLayout}
      storesData={storesData}
      popularProducts={popularProducts}
      sortedSlots={sortedSlots}
      onProductPress={handleProductPress}
    />
  ), [gradientHeight, handleGradientLayout, storesData, popularProducts, sortedSlots, handleProductPress]);

  const searchBarContainerStyle = useMemo(() => [
    tw`w-full px-4 pt-4 pb-2`,
    { backgroundColor }
  ], [backgroundColor]);

  const listContentContainerStyle = useMemo(() => [
    tw`pb-24`,
    staticStyles.flatListContent
  ], []);

  if (isLoading || isLoadingConsts) {
    return (
      <View style={tw`flex-1 justify-center items-center bg-gray-50`}>
        <MyText style={tw`text-gray-500 font-medium`}>
          {isLoading ? 'Loading products...' : 'Loading app settings...'}
        </MyText>
      </View>
    );
  }

  if (error || constsError) {
    return (
      <View style={tw`flex-1 justify-center items-center bg-gray-50`}>
        <MaterialIcons name="error-outline" size={48} color="#EF4444" />
        <MyText style={tw`text-gray-900 text-lg font-bold mt-4`}>Oops!</MyText>
        <MyText style={tw`text-gray-500 mt-2`}>
          {error ? 'Failed to load products' : 'Failed to load app settings'}
        </MyText>
      </View>
    );
  }

  return (
    <TabLayoutWrapper>
      <View style={searchBarContainerStyle}>
        <SearchBar
          value={""}
          onChangeText={() => { }}
          onPress={handleSearchPress}
          editable={false}
          containerStyle={tw`bg-white`}
          onSubmitEditing={() => {
            if (inputQuery.trim()) {
              router.push(`/(drawer)/(tabs)/home/search-results?q=${encodeURIComponent(inputQuery.trim())}`);
            }
          }}
          returnKeyType="search"
        />
      </View>

      <MyFlatList
        data={displayedProducts}
        keyExtractor={(item) => item.id.toString()}
        numColumns={2}
        contentContainerStyle={listContentContainerStyle}
        columnWrapperStyle={staticStyles.columnWrapper}
        renderItem={renderProductItem}
        ListHeaderComponent={listHeader}
        refreshControl={
          <RefreshControl
            refreshing={isRefreshing}
            onRefresh={handleRefresh}
            tintColor="#3b82f6"
            colors={["#3b82f6"]}
          />
        }
        ListEmptyComponent={
          <View style={tw`items-center py-8`}>
            <MyText style={tw`text-gray-500`}>No products available</MyText>
          </View>
        }
        removeClippedSubviews={true}
        maxToRenderPerBatch={10}
        windowSize={5}
        initialNumToRender={10}
        updateCellsBatchingPeriod={50}
      />

      <LoadingDialog open={isLoadingDialogOpen} message="Adding to cart..." />
      <AddToCartDialog />
      <View style={tw`absolute bottom-2 left-4 right-4`}>
        <FloatingCartBar />
      </View>
    </TabLayoutWrapper>
  );
}
