import HeaderRightAnnouncementDetail from "@/components/announcement/headerAnnouncementDetail";
import AppHeader from "@/components/AppHeader";
import BorderBottomItem from "@/components/borderBottomItem";
import Skeleton from "@/components/skeleton";
import Text from '@/components/Text';
import ErrorView from "@/components/ErrorView";
import { ConstEnv } from "@/constants/ConstEnv";
import { isImageFile } from "@/constants/FileExtensions";
import Styles from "@/constants/Styles";
import { apiGetAnnouncementOne } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { Entypo, MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
import * as FileSystem from 'expo-file-system';
import { startActivityAsync } from 'expo-intent-launcher';
import { router, Stack, useLocalSearchParams } from "expo-router";
import * as Sharing from 'expo-sharing';
import React, { useEffect, useState } from "react";
import { Dimensions, Platform, Pressable, RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
import ImageViewing from 'react-native-image-viewing';
import * as mime from 'react-native-mime-types';
import RenderHTML from 'react-native-render-html';
import Toast from "react-native-toast-message";
import { useSelector } from "react-redux";

// Define TypeScript interfaces for better type safety
interface AnnouncementData {
   id: string;
   title: string;
   desc: string;
}

interface FileData {
   id: string;
   idStorage: string;
   name: string;
   extension: string;
}

interface MemberData {
   group: string;
   division: string;
}

interface ApiResponse {
   success: boolean;
   data: AnnouncementData;
   member: Record<string, MemberData[]>;
   file: FileData[];
   message: string;
}

export default function DetailAnnouncement() {
   const { id } = useLocalSearchParams<{ id: string }>();
   const { token, decryptToken } = useAuthSession()
   const { colors } = useTheme();
   const [data, setData] = useState<AnnouncementData>({ id: '', title: '', desc: '' })
   const [dataMember, setDataMember] = useState<Record<string, MemberData[]>>({})
   const [dataFile, setDataFile] = useState<FileData[]>([])
   const update = useSelector((state: any) => state.announcementUpdate)
   const entityUser = useSelector((state: any) => state.user)
   const contentWidth = Dimensions.get('window').width
   const [loading, setLoading] = useState(true)
   const arrSkeleton = Array.from({ length: 2 }, (_, index) => index)
   const [refreshing, setRefreshing] = useState(false)
   const [loadingOpen, setLoadingOpen] = useState(false)
   const [preview, setPreview] = useState(false)
   const [chooseFile, setChooseFile] = useState<FileData>()
   const [isError, setIsError] = useState(false)

   /**
    * Opens the image preview modal for the selected image file
    * @param item The file data object containing image information
    */

   function handleChooseFile(item: FileData) {
      setChooseFile(item)
      setPreview(true)
   }


   async function handleLoad(loading: boolean) {
      try {
         setIsError(false)
         setLoading(loading)
         const hasil = await decryptToken(String(token?.current))
         const response: ApiResponse = await apiGetAnnouncementOne({ id: id, user: hasil })
         if (response.success) {
            setData(response.data)
            setDataMember(response.member)
            setDataFile(response.file)
         } else {
            setIsError(true)
            Toast.show({ type: 'small', text1: response.message })
         }
      } catch (error: any) {
         console.error(error);
         setIsError(true)
         const message = error?.response?.data?.message || "Gagal mengambil data"

         Toast.show({ type: 'small', text1: message })
      } finally {
         setLoading(false)
      }
   }

   useEffect(() => {
      handleLoad(false)
   }, [update])

   useEffect(() => {
      handleLoad(true)
   }, [])

   /**
    * Checks if a string contains HTML tags
    * @param text The text to check for HTML tags
    * @returns True if the text contains HTML tags, false otherwise
    */
   function hasHtmlTags(text: string) {
      const htmlRegex = /<[a-z][\s\S]*>/i;
      return htmlRegex.test(text);
   }

   /**
    * Handles pull-to-refresh functionality
    * Reloads the announcement data without showing loading indicators
    */
   const handleRefresh = async () => {
      setRefreshing(true)
      handleLoad(false)
      // Simulate network request delay for better UX
      await new Promise(resolve => setTimeout(resolve, 2000));
      setRefreshing(false)
   };

   const openFile = async (item: FileData) => {
      try {
         setLoadingOpen(true);
         const remoteUrl = ConstEnv.url_storage + '/files/' + item.idStorage;
         const fileName = item.name + '.' + item.extension;
         const localPath = `${FileSystem.documentDirectory}/${fileName}`;
         const mimeType = mime.lookup(fileName);

         // Download the file
         const downloadResult = await FileSystem.downloadAsync(remoteUrl, localPath);

         if (downloadResult.status !== 200) {
            throw new Error(`Download failed with status ${downloadResult.status}`);
         }

         const contentURL = await FileSystem.getContentUriAsync(downloadResult.uri);

         try {
            if (Platform.OS === 'android') {
               await startActivityAsync(
                  'android.intent.action.VIEW',
                  {
                     data: contentURL,
                     flags: 1,
                     type: mimeType as string,
                  }
               );
            } else if (Platform.OS === 'ios') {
               await Sharing.shareAsync(localPath);
            }
         } catch (openError) {
            console.error('Error opening file:', openError);
            Toast.show({
               type: 'error',
               text1: 'Tidak ada aplikasi yang dapat membuka file ini'
            });
         }
      } catch (error) {
         console.error('Error downloading or opening file:', error);
         Toast.show({
            type: 'error',
            text1: 'Gagal membuka file',
            text2: 'Silakan coba lagi nanti'
         });
      } finally {
         setLoadingOpen(false);
      }
   };

   return (
      <SafeAreaView style={[Styles.flex1, { backgroundColor: colors.background }]}>
         <Stack.Screen
            options={{
               // headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
               headerTitle: 'Pengumuman',
               headerTitleAlign: 'center',
               // headerRight: () => entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>,
               header: () => (
                  <AppHeader title="Pengumuman"
                     showBack={true}
                     onPressLeft={() => router.back()}
                     right={entityUser.role != 'user' && entityUser.role != 'coadmin' ? <HeaderRightAnnouncementDetail id={id} /> : <></>}
                  />
               )
            }}
         />
         <ScrollView
            showsVerticalScrollIndicator={false}
            style={[Styles.h100, { backgroundColor: colors.background }]}
            refreshControl={
               <RefreshControl
                  refreshing={refreshing}
                  onRefresh={() => handleRefresh()}
                  tintColor={colors.icon}
               />
            }
         >
            {isError && !loading ? (
               <View style={[Styles.mv50]}>
                  <ErrorView />
               </View>
            ) : (
               <View style={[Styles.p15, Styles.mb50]}>
                  <View style={[Styles.wrapPaper, Styles.borderAll, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
                     {
                        loading ?
                           <View>
                              <View style={[Styles.rowOnly]}>
                                 <Skeleton width={30} height={30} borderRadius={10} />
                                 <View style={[Styles.flex1, Styles.ph05]}>
                                    <Skeleton width={100} widthType="percent" height={30} borderRadius={10} />
                                 </View>
                              </View>
                              <Skeleton width={100} widthType="percent" height={10} borderRadius={10} />
                              <Skeleton width={100} widthType="percent" height={10} borderRadius={10} />
                              <Skeleton width={100} widthType="percent" height={10} borderRadius={10} />
                           </View>
                           :
                           <>
                              <View style={[Styles.rowOnly, Styles.alignStart]}>
                                 <MaterialIcons name="campaign" size={25} color={colors.text} style={[Styles.mr05]} />
                                 <Text style={[Styles.textDefaultSemiBold, Styles.w90, Styles.mt02]}>{data?.title}</Text>
                              </View>
                              <View style={[Styles.mt10]}>
                                 {
                                    hasHtmlTags(data?.desc) ?
                                       <RenderHTML
                                          contentWidth={contentWidth}
                                          source={{ html: data?.desc }}
                                          baseStyle={{ color: colors.text }}
                                       />
                                       :
                                       <Text>{data?.desc}</Text>
                                 }
                              </View>
                           </>
                     }

                  </View>
                  {
                     dataFile.length > 0 && (
                        <View style={[Styles.wrapPaper, Styles.borderAll, Styles.mt10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
                           <View style={[Styles.mb05]}>
                              <Text style={[Styles.textDefaultSemiBold]}>File</Text>
                           </View>
                           {dataFile.map((item, index) => (
                              <BorderBottomItem
                                 key={`${item.id}-${index}`}
                                 borderType={index === dataFile.length - 1 ? 'none' : 'bottom'}
                                 icon={<MaterialCommunityIcons
                                    name={isImageFile(item.extension) ? "file-image-outline" : "file-document-outline"}
                                    size={25}
                                    color={colors.text}
                                 />}
                                 title={item.name + '.' + item.extension}
                                 titleWeight="normal"
                                 onPress={() => {
                                    isImageFile(item.extension) ?
                                       handleChooseFile(item)
                                       : openFile(item)
                                 }}
                              />
                           ))}
                        </View>
                     )
                  }
                  <View style={[Styles.wrapPaper, Styles.borderAll, Styles.mt10, { backgroundColor: colors.card, borderColor: colors.icon + '20' }]}>
                     {
                        loading ?
                           arrSkeleton.map((item, index) => {
                              return (
                                 <View key={index}>
                                    <Skeleton width={30} widthType="percent" height={10} borderRadius={10} />
                                    <Skeleton width={100} widthType="percent" height={10} borderRadius={10} />
                                    <Skeleton width={100} widthType="percent" height={10} borderRadius={10} />
                                 </View>
                              )
                           })
                           :
                           Object.keys(dataMember).map((v: any, i: any) => {
                              return (
                                 <View key={i} style={[Styles.mb05]}>
                                    <Text style={[Styles.textDefaultSemiBold]}>{dataMember[v]?.[0].group}</Text>
                                    {
                                       dataMember[v].map((item: any, x: any) => {
                                          return (
                                             <View key={x} style={[Styles.rowItemsCenter, Styles.w90]}>
                                                <Entypo name="dot-single" size={24} color={colors.text} />
                                                <Text style={[Styles.textDefault]} numberOfLines={1} ellipsizeMode='tail'>{item.division}</Text>
                                             </View>
                                          )
                                       })
                                    }

                                 </View>
                              )
                           })
                     }
                  </View>
               </View>
            )}
         </ScrollView>

         <ImageViewing
            images={[{ uri: `${ConstEnv.url_storage}/files/${chooseFile?.idStorage}` }]}
            imageIndex={0}
            visible={preview}
            onRequestClose={() => setPreview(false)}
            doubleTapToZoomEnabled
            HeaderComponent={({ imageIndex }) => (
               <View style={[Styles.headerModalViewImg]}>
                  {/* CLOSE */}
                  <Pressable
                     onPress={() => setPreview(false)}
                     accessibilityRole="button"
                     accessibilityLabel="Close image viewer"
                  >
                     <Text style={[Styles.textWhite, Styles.font26]}>✕</Text>
                  </Pressable>

                  {/* MENU */}
                  <Pressable
                     onPress={() => chooseFile && openFile(chooseFile)}
                     accessibilityRole="button"
                     accessibilityLabel="Download or share image"
                     disabled={loadingOpen}
                  >
                     <Text style={[{ color: loadingOpen ? 'gray' : 'white' }, Styles.font26]}>⋯</Text>
                  </Pressable>
               </View>
            )}
            FooterComponent={({ imageIndex }) => (
               <View style={[
                  Styles.pb20,
                  Styles.ph16,
                  Styles.alignCenter,
               ]}>
                  <Text style={[Styles.textWhite, Styles.font16]}>{chooseFile?.name}.{chooseFile?.extension}</Text>
               </View>
            )}
         />
      </SafeAreaView>
   )
}