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 { router, Stack } from "expo-router";
import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useMemo } from "react";
import { FlatList, Pressable, RefreshControl, SafeAreaView, View } from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { useState } from "react";

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 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)
      })

      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)
      }
   }

   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={22} 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, { paddingTop: 10 }]}>
            {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, { marginTop: 16, marginBottom: 8 }]}>
                              <Text style={{ fontSize: 11, fontWeight: '600', color: colors.dimmed, letterSpacing: 0.6, textTransform: 'uppercase' }}>
                                 {item.date}
                              </Text>
                              <View style={{ flex: 1, height: 1, backgroundColor: colors.icon + '20', marginLeft: 8 }} />
                           </View>
                        )
                     }

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

                     return (
                        <Pressable
                           onPress={() => handleReadNotification(item.id, item.category, item.idContent)}
                           style={({ pressed }) => [{
                              flexDirection: 'row',
                              alignItems: 'center',
                              borderRadius: 10,
                              borderWidth: 1,
                              borderColor: colors.icon + '20',
                              backgroundColor: pressed
                                 ? colors.icon + '10'
                                 : item.isRead
                                    ? colors.icon + '10'
                                    : colors.card,
                              paddingHorizontal: 12,
                              paddingVertical: 10,
                              marginBottom: 6,
                           }]}
                        >
                           {/* Colored icon */}
                           <View style={{
                              width: 42,
                              height: 42,
                              borderRadius: 21,
                              backgroundColor: color + '20',
                              alignItems: 'center',
                              justifyContent: 'center',
                              flexShrink: 0,
                           }}>
                              <Feather name={icon} size={20} color={color} />
                           </View>

                           {/* Content */}
                           <View style={[Styles.flex1, { marginLeft: 10 }]}>
                              <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>
                              </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>
   )
}
