import AppHeader from "@/components/AppHeader";
import ModalConfirmation from "@/components/ModalConfirmation";
import SkeletonTwoItem from "@/components/skeletonTwoItem";
import Text from "@/components/Text";
import Styles from "@/constants/Styles";
import { apiGetNotification, apiReadAllNotification, apiReadOneNotification } from "@/lib/api";
import { setUpdateNotification } from "@/lib/notificationSlice";
import { pushToPage } from "@/lib/pushToPage";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { Feather } from "@expo/vector-icons";
import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query";
import { router, Stack } from "expo-router";
import { useEffect, useMemo, useState } from "react";
import { FlatList, Pressable, RefreshControl, SafeAreaView, View } from "react-native";
import { useDispatch, useSelector } from "react-redux";

type Props = {
   id: string
   title: string
   desc: string
   category: string
   idContent: string
   isRead: boolean
   createdAt: string
}

type HeaderRow = { _type: 'header'; date: string }
type ItemRow = Props & { _type: 'item' }
type ListRow = HeaderRow | ItemRow

function getNotifStyle(category: string): { icon: keyof typeof Feather.glyphMap; color: string } {
   if (category === 'announcement') return { icon: 'volume-2', color: '#3B82F6' }
   if (category === 'project') return { icon: 'activity', color: '#10B981' }
   if (category.includes('/task')) return { icon: 'clipboard', color: '#8B5CF6' }
   if (category === 'division') return { icon: 'users', color: '#3B82F6' }
   if (category.includes('/discussion') || category === 'discussion-general') return { icon: 'message-square', color: '#06B6D4' }
   if (category.includes('/calendar')) return { icon: 'calendar', color: '#F59E0B' }
   if (category.includes('/document')) return { icon: 'file-text', color: '#FBBF24' }
   if (category === 'member') return { icon: 'user', color: '#1F3C88' }
   return { icon: 'bell', color: '#6B7280' }
}

export default function Notification() {
   const { token, decryptToken } = useAuthSession()
   const { colors } = useTheme();
   const queryClient = useQueryClient()
   const dispatch = useDispatch()
   const updateNotification = useSelector((state: any) => state.notificationUpdate)
   const [refreshing, setRefreshing] = useState(false)
   const [markingAll, setMarkingAll] = useState(false)
   const [showConfirm, setShowConfirm] = useState(false)

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

   const flatData = useMemo(() => {
      return data?.pages.flatMap(page => page.data) || [];
   }, [data])

   const listData = useMemo<ListRow[]>(() => {
      const BULAN: Record<string, number> = {
         'JAN': 0, 'FEB': 1, 'MAR': 2, 'APR': 3, 'MEI': 4, 'JUN': 5,
         'JUL': 6, 'AGU': 7, 'SEP': 8, 'OKT': 9, 'NOV': 10, 'DES': 11,
      }
      const parseDate = (str: string) => {
         const [d, m, y] = str.split(' ')
         return new Date(Number(y), BULAN[m?.toUpperCase()] ?? 0, Number(d)).getTime()
      }

      const groups: Record<string, Props[]> = {}
      const dateOrder: string[] = []

      flatData.forEach((item) => {
         if (!groups[item.createdAt]) {
            groups[item.createdAt] = []
            dateOrder.push(item.createdAt)
         }
         groups[item.createdAt].push(item)
      })

      dateOrder.sort((a, b) => parseDate(b) - parseDate(a))

      const result: ListRow[] = []
      dateOrder.forEach((date) => {
         result.push({ _type: 'header', date })
         const sorted = [...groups[date]].sort((a, b) => Number(a.isRead) - Number(b.isRead))
         sorted.forEach((item) => result.push({ ...item, _type: 'item' }))
      })
      return result
   }, [flatData])

   useEffect(() => {
      refetch()
   }, [updateNotification, refetch])

   const handleRefresh = async () => {
      setRefreshing(true)
      await queryClient.invalidateQueries({ queryKey: ['notifications'] })
      setRefreshing(false)
   };

   const hasUnread = flatData.some((item) => !item.isRead)

   async function handleReadAll() {
      try {
         setMarkingAll(true)
         const hasil = await decryptToken(String(token?.current))
         await apiReadAllNotification({ user: hasil })
         await queryClient.invalidateQueries({ queryKey: ['notifications'] })
         dispatch(setUpdateNotification(!updateNotification))
      } catch (error) {
         console.error(error)
      } finally {
         setMarkingAll(false)
      }
   }

   async function handleReadNotification(id: string, category: string, idContent: string) {
      try {
         const hasil = await decryptToken(String(token?.current))
         await apiReadOneNotification({ user: hasil, id: id })
         await queryClient.invalidateQueries({ queryKey: ['notifications'] })
         pushToPage(category, idContent)
         dispatch(setUpdateNotification(!updateNotification))
      } catch (error) {
         console.error(error)
      }
   }

   async function handleMarkOneRead(id: string) {
      try {
         const hasil = await decryptToken(String(token?.current))
         await apiReadOneNotification({ user: hasil, id: id })
         await queryClient.invalidateQueries({ queryKey: ['notifications'] })
         dispatch(setUpdateNotification(!updateNotification))
      } catch (error) {
         console.error(error)
      }
   }

   return (
      <SafeAreaView style={[Styles.flex1, { backgroundColor: colors.background }]}>
         <Stack.Screen
            options={{
               header: () => (
                  <AppHeader
                     title="Notifikasi"
                     showBack={true}
                     onPressLeft={() => router.back()}
                     right={
                        hasUnread ? (
                           <Pressable
                              onPress={() => setShowConfirm(true)}
                              disabled={markingAll}
                              style={{ opacity: markingAll ? 0.5 : 1, padding: 4 }}
                           >
                              <Feather name="check-square" size={20} color="white" />
                           </Pressable>
                        ) : undefined
                     }
                  />
               )
            }}
         />

         <ModalConfirmation
            visible={showConfirm}
            title="Tandai Semua Dibaca"
            message="Semua notifikasi akan ditandai sebagai telah dibaca."
            confirmText="Tandai"
            cancelText="Batal"
            onConfirm={() => {
               setShowConfirm(false)
               handleReadAll()
            }}
            onCancel={() => setShowConfirm(false)}
         />


<View style={[Styles.flex1, Styles.ph15, Styles.notifContainer]}>
            {isLoading ? (
               [0, 1, 2, 3, 4].map((_, i) => <SkeletonTwoItem key={i} />)
            ) : flatData.length === 0 ? (
               <View style={[Styles.contentItemCenter, Styles.mt30]}>
                  <Feather name="bell-off" size={42} color={colors.icon + '40'} />
                  <Text style={[Styles.mt10, { color: colors.dimmed, fontSize: 14 }]}>
                     Tidak ada notifikasi
                  </Text>
               </View>
            ) : (
               <FlatList
                  data={listData}
                  keyExtractor={(item, index) => String(index)}
                  showsVerticalScrollIndicator={false}
                  onEndReached={() => {
                     if (hasNextPage && !isFetchingNextPage) fetchNextPage()
                  }}
                  onEndReachedThreshold={0.5}
                  refreshControl={
                     <RefreshControl
                        refreshing={refreshing}
                        onRefresh={handleRefresh}
                        tintColor={colors.icon}
                     />
                  }
                  renderItem={({ item }) => {
                     if (item._type === 'header') {
                        return (
                           <View style={[Styles.rowItemsCenter, Styles.notifHeaderRow]}>
                              <Text style={[Styles.notifDateText, { color: colors.dimmed }]}>
                                 {item.date}
                              </Text>
                              <View style={[Styles.notifDateSeparator, { backgroundColor: colors.icon + '20' }]} />
                           </View>
                        )
                     }

                     const { icon, color } = getNotifStyle(item.category)

                     return (
                        <Pressable
                           onPress={() => handleReadNotification(item.id, item.category, item.idContent)}
                           style={({ pressed }) => [Styles.notifItemRow, {
                              borderColor: colors.icon + '20',
                              backgroundColor: pressed
                                 ? colors.icon + '10'
                                 : item.isRead
                                    ? colors.icon + '10'
                                    : colors.card,
                           }]}
                        >
                           <View style={[Styles.notifIconContainer, { backgroundColor: color + '20' }]}>
                              <Feather name={icon} size={20} color={color} />
                           </View>

                           <View style={[Styles.flex1, Styles.notifContent]}>
                              <View style={[Styles.rowSpaceBetween, Styles.itemsCenter]}>
                                 <View style={[Styles.flex1, Styles.mr10]}>
                                    <Text
                                       style={[Styles.textDefaultSemiBold, { color: item.isRead ? colors.dimmed : colors.text }]}
                                       numberOfLines={1}
                                    >
                                       {item.title}
                                    </Text>
                                 </View>
                                 {!item.isRead && (
                                    <Pressable
                                       onPress={(e) => {
                                          e.stopPropagation()
                                          handleMarkOneRead(item.id)
                                       }}
                                       hitSlop={8}
                                       style={({ pressed }) => ({ opacity: pressed ? 0.5 : 1, flexShrink: 0 })}
                                    >
                                       <Text style={Styles.notifMarkReadText}>
                                          Tandai dibaca
                                       </Text>
                                    </Pressable>
                                 )}
                              </View>
                              <Text
                                 style={[Styles.textMediumNormal, { color: item.isRead ? colors.dimmed : colors.text, opacity: item.isRead ? 0.7 : 1 }]}
                                 numberOfLines={2}
                              >
                                 {item.desc}
                              </Text>
                           </View>
                        </Pressable>
                     )
                  }}
               />
            )}
         </View>
      </SafeAreaView>
   )
}
