import GuideOverlay from "@/components/GuideOverlay";
import InputSearch from "@/components/inputSearch";
import Skeleton from "@/components/skeleton";
import Text from '@/components/Text';
import Styles from "@/constants/Styles";
import { apiGetAnnouncement } from "@/lib/api";
import { GUIDE_ANNOUNCEMENT } from "@/lib/guideSteps";
import { useGuide } from "@/lib/useGuide";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { MaterialIcons } from "@expo/vector-icons";
import { useInfiniteQuery } from "@tanstack/react-query";
import { router } from "expo-router";
import { useEffect, useMemo, useRef, useState } from "react";
import { Pressable, RefreshControl, View, VirtualizedList } from "react-native";
import { useSelector } from "react-redux";

type Props = {
   id: string
   title: string
   desc: string
   createdAt: string
}

export default function Announcement() {
   const { token, decryptToken } = useAuthSession()
   const { colors } = useTheme();
   const [search, setSearch] = useState('')
   const update = useSelector((state: any) => state.announcementUpdate)
   const isFirstRender = useRef(true)
   const { visible: guideVisible, dismiss: dismissGuide } = useGuide('announcement')
   const arrSkeleton = Array.from({ length: 5 }, (_, i) => i)

   const themed = {
      background:  { backgroundColor: colors.background },
      card:        { backgroundColor: colors.card, borderColor: colors.icon + '18' },
      iconBox:     { backgroundColor: colors.icon + '18' },
      title:       { color: colors.text },
      desc:        { color: colors.dimmed },
      date:        { color: colors.dimmed },
      cardPressed: { backgroundColor: colors.icon + '08' },
   }

   const {
      data,
      fetchNextPage,
      hasNextPage,
      isFetchingNextPage,
      isLoading,
      refetch,
      isRefetching
   } = useInfiniteQuery({
      queryKey: ['announcements', search],
      queryFn: async ({ pageParam = 1 }) => {
         const hasil = await decryptToken(String(token?.current))
         const response = await apiGetAnnouncement({ user: hasil, search, page: pageParam })
         return response.data
      },
      initialPageParam: 1,
      getNextPageParam: (lastPage, allPages) => {
         return lastPage.length > 0 ? allPages.length + 1 : undefined
      },
   })

   useEffect(() => {
      if (isFirstRender.current) { isFirstRender.current = false; return }
      refetch()
   }, [update])

   const flattenedData = useMemo(() => data?.pages.flat() || [], [data])

   const getItem = (_data: unknown, index: number): Props => ({
      id: flattenedData[index].id,
      title: flattenedData[index].title,
      desc: flattenedData[index].desc,
      createdAt: flattenedData[index].createdAt,
   })

   const renderSkeleton = () => (
      <View style={Styles.announcementListSkeletonCard}>
         <View style={[Styles.rowSpaceBetween, Styles.rowItemsCenter, Styles.announcementListSkeletonHeader]}>
            <View style={[Styles.rowItemsCenter, Styles.announcementListSkeletonTitleRow]}>
               <Skeleton width={28} height={28} borderRadius={8} />
               <Skeleton width={50} widthType="percent" height={12} borderRadius={6} />
            </View>
            <Skeleton width={15} widthType="percent" height={10} borderRadius={6} />
         </View>
         <Skeleton width={100} widthType="percent" height={10} borderRadius={6} />
         <Skeleton width={80} widthType="percent" height={10} borderRadius={6} />
      </View>
   )

   const renderItem = ({ item }: { item: Props }) => (
      <Pressable
         onPress={() => router.push(`/announcement/${item.id}`)}
         style={({ pressed }) => [Styles.announcementListCard, themed.card, pressed && themed.cardPressed]}
      >
         <View style={[Styles.rowSpaceBetween, Styles.rowItemsCenter, Styles.announcementListCardHeader]}>
            <View style={[Styles.rowItemsCenter, Styles.announcementListTitleRow]}>
               <View style={[Styles.announcementListIconBox, themed.iconBox]}>
                  <MaterialIcons name="campaign" size={16} color={colors.icon} />
               </View>
               <Text style={[Styles.textDefaultSemiBold, Styles.announcementListTitleText, themed.title]} numberOfLines={1}>
                  {item.title}
               </Text>
            </View>
            <Text style={[Styles.textInformation, Styles.announcementListDateText, themed.date]}>
               {item.createdAt}
            </Text>
         </View>
         <Text style={[Styles.textMediumNormal, Styles.announcementListDescText, themed.title]} numberOfLines={2}>
            {item.desc.replace(/<[^>]*>?/gm, '').replace(/\r?\n|\r/g, ' ')}
         </Text>
      </Pressable>
   )

   return (
      <View style={[Styles.flex1, Styles.announcementListContainer, themed.background]}>
         <GuideOverlay visible={guideVisible} steps={GUIDE_ANNOUNCEMENT} onDismiss={dismissGuide} />
         <InputSearch onChange={setSearch} />
         <View style={[Styles.flex1, Styles.announcementListInner]}>
            {isLoading && !flattenedData.length ? (
               arrSkeleton.map((_, i) => (
                  <View key={i} style={[Styles.announcementListCard, themed.card]}>
                     {renderSkeleton()}
                  </View>
               ))
            ) : flattenedData.length > 0 ? (
               <VirtualizedList
                  data={flattenedData}
                  getItemCount={() => flattenedData.length}
                  getItem={getItem}
                  renderItem={renderItem}
                  keyExtractor={(item, index) => String(item.id || index)}
                  onEndReached={() => { if (hasNextPage && !isFetchingNextPage) fetchNextPage() }}
                  onEndReachedThreshold={0.5}
                  showsVerticalScrollIndicator={false}
                  ItemSeparatorComponent={() => <View style={Styles.announcementListSeparator} />}
                  refreshControl={
                     <RefreshControl
                        refreshing={isRefetching && !isFetchingNextPage}
                        onRefresh={refetch}
                        tintColor={colors.icon}
                     />
                  }
               />
            ) : (
               <Text style={[Styles.textDefault, Styles.textCenter, Styles.mt30, themed.desc]}>
                  Tidak ada pengumuman
               </Text>
            )}
         </View>
      </View>
   )
}
