import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import ImageUser from "@/components/imageNew";
import ImageWithLabel from "@/components/imageWithLabel";
import InputSearch from "@/components/inputSearch";
import Text from '@/components/Text';
import { ConstEnv } from "@/constants/ConstEnv";
import Styles from "@/constants/Styles";
import { apiAddMemberDiscussionGeneral, apiGetDiscussionGeneralOne, apiGetDivision, apiGetDivisionMember, apiGetUser } from "@/lib/api";
import { setUpdateDiscussionGeneralDetail } from "@/lib/discussionGeneralDetail";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { AntDesign, Ionicons } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { ActivityIndicator, Pressable, ScrollView, View } from "react-native";
import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux";

type Member = { idUser: string; name: string; img: string }

type DivisionItem = {
   id: string
   name: string
   expanded: boolean
   membersLoaded: boolean
   members: Member[]
}

export default function AddMemberDiscussionDetail() {
   const dispatch = useDispatch()
   const update = useSelector((state: any) => state.discussionGeneralDetailUpdate)
   const { token, decryptToken } = useAuthSession()
   const { colors } = useTheme()
   const { id } = useLocalSearchParams<{ id: string }>()
   const [dataOld, setDataOld] = useState<any[]>([])
   const [idGroup, setIdGroup] = useState('')
   const [selectMember, setSelectMember] = useState<Member[]>([])
   const [search, setSearch] = useState('')
   const [loading, setLoading] = useState(false)
   const [divisions, setDivisions] = useState<DivisionItem[]>([])
   const [loadingDivisions, setLoadingDivisions] = useState(false)
   const [loadingIds, setLoadingIds] = useState<string[]>([])
   const [searchResults, setSearchResults] = useState<Member[]>([])
   const [loadingSearch, setLoadingSearch] = useState(false)

   async function handleLoad() {
      try {
         const hasil = await decryptToken(String(token?.current))
         const [resAnggota, resDetail] = await Promise.all([
            apiGetDiscussionGeneralOne({ id, user: hasil, cat: 'anggota' }),
            apiGetDiscussionGeneralOne({ id, user: hasil, cat: 'detail' })
         ])
         setDataOld(resAnggota.data ?? [])
         setIdGroup(resDetail.data.idGroup)
      } catch (error) {
         console.error(error)
      }
   }

   async function loadDivisions(group: string) {
      if (!group) return
      setLoadingDivisions(true)
      try {
         const hasil = await decryptToken(String(token?.current))
         const response = await apiGetDivision({ user: hasil, search: '', group, active: 'true', kategori: 'semua', page: 1 })
         const divisionList: DivisionItem[] = (response.data ?? []).map((d: any) => ({
            id: d.id, name: d.name, expanded: false, membersLoaded: false, members: []
         }))
         const withMembers = await Promise.all(
            divisionList.map(async (d) => {
               try {
                  const res = await apiGetDivisionMember({ user: hasil, id: d.id, search: '' })
                  const members: Member[] = (res.data ?? []).map((m: any) => ({ idUser: m.idUser, name: m.name, img: m.img }))
                  return { ...d, members, membersLoaded: true }
               } catch {
                  return { ...d, membersLoaded: true }
               }
            })
         )
         setDivisions(withMembers)
      } catch { setDivisions([]) }
      finally { setLoadingDivisions(false) }
   }

   async function fetchMembers(divisionId: string): Promise<Member[]> {
      setLoadingIds(prev => [...prev, divisionId])
      try {
         const hasil = await decryptToken(String(token?.current))
         const response = await apiGetDivisionMember({ user: hasil, id: divisionId, search: '' })
         const members: Member[] = (response.data ?? []).map((m: any) => ({ idUser: m.idUser, name: m.name, img: m.img }))
         setDivisions(prev => prev.map(d =>
            d.id === divisionId ? { ...d, members, membersLoaded: true } : d
         ))
         return members
      } catch { return [] }
      finally { setLoadingIds(prev => prev.filter(i => i !== divisionId)) }
   }

   async function searchUsers(query: string) {
      if (!idGroup) return
      setLoadingSearch(true)
      try {
         const hasil = await decryptToken(String(token?.current))
         const response = await apiGetUser({ user: hasil, active: 'true', search: query, group: idGroup })
         setSearchResults((response.data ?? [])
            .filter((i: any) => i.idUserRole !== 'supadmin')
            .map((i: any) => ({ idUser: i.id, name: i.name, img: i.img }))
         )
      } catch { setSearchResults([]) }
      finally { setLoadingSearch(false) }
   }

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

   useEffect(() => {
      if (idGroup) loadDivisions(idGroup)
   }, [idGroup])

   useEffect(() => {
      if (!idGroup) return
      if (search) {
         searchUsers(search)
      } else {
         setSearchResults([])
         loadDivisions(idGroup)
      }
   }, [search])

   async function handleTapDivision(division: DivisionItem) {
      let members = division.members
      if (!division.membersLoaded) members = await fetchMembers(division.id)
      setDivisions(prev => prev.map(d =>
         d.id === division.id ? { ...d, expanded: true, members, membersLoaded: true } : d
      ))
      const eligible = members.filter(m => !dataOld.some((o: any) => o.idUser === m.idUser))
      const allSelected = eligible.length > 0 && eligible.every(m =>
         selectMember.some(s => s.idUser === m.idUser)
      )
      if (allSelected) {
         setSelectMember(prev => prev.filter(s => !eligible.some(m => m.idUser === s.idUser)))
      } else {
         const existingIds = new Set(selectMember.map(s => s.idUser))
         setSelectMember(prev => [...prev, ...eligible.filter(m => !existingIds.has(m.idUser))])
      }
   }

   async function handleToggleExpand(divisionId: string) {
      const division = divisions.find(d => d.id === divisionId)!
      if (!division.membersLoaded && !division.expanded) await fetchMembers(divisionId)
      setDivisions(prev => prev.map(d =>
         d.id === divisionId ? { ...d, expanded: !d.expanded } : d
      ))
   }

   function handleToggleMember(member: Member) {
      if (dataOld.some((o: any) => o.idUser === member.idUser)) return
      if (selectMember.some(s => s.idUser === member.idUser)) {
         setSelectMember(prev => prev.filter(s => s.idUser !== member.idUser))
      } else {
         setSelectMember(prev => [...prev, member])
      }
   }

   async function handleAddMember() {
      try {
         setLoading(true)
         const hasil = await decryptToken(String(token?.current))
         const response = await apiAddMemberDiscussionGeneral({ id, data: { user: hasil, member: selectMember } })
         if (response.success) {
            Toast.show({ type: 'small', text1: 'Berhasil menambahkan anggota' })
            dispatch(setUpdateDiscussionGeneralDetail(!update))
            router.back()
         } else {
            Toast.show({ type: 'small', text1: response.message })
         }
      } catch (error: any) {
         console.error(error)
         Toast.show({ type: 'small', text1: error?.response?.data?.message || "Gagal menambahkan anggota" })
      } finally {
         setLoading(false)
      }
   }

   return (
      <>
         <Stack.Screen
            options={{
               header: () => (
                  <AppHeader
                     title="Tambah Anggota Diskusi"
                     showBack={true}
                     onPressLeft={() => router.back()}
                     right={
                        <ButtonSaveHeader
                           category="update"
                           disable={selectMember.length === 0 || loading}
                           onPress={handleAddMember}
                        />
                     }
                  />
               )
            }}
         />
         <View style={[Styles.p15, Styles.flex1, { backgroundColor: colors.background }]}>
            <InputSearch onChange={setSearch} value={search} />
            {selectMember.length > 0 ? (
               <View>
                  <ScrollView horizontal style={[Styles.mb10, Styles.pv10]} showsHorizontalScrollIndicator={false}>
                     {selectMember.map((item, index) => (
                        <ImageWithLabel
                           key={index}
                           label={item.name}
                           src={`${ConstEnv.url_storage}/files/${item.img}`}
                           onClick={() => handleToggleMember(item)}
                        />
                     ))}
                  </ScrollView>
               </View>
            ) : (
               <Text style={[Styles.textDefault, Styles.pv05, Styles.textCenter, { color: colors.dimmed }]}>
                  Tidak ada member yang dipilih
               </Text>
            )}
            <ScrollView showsVerticalScrollIndicator={false}>
               <View>
                  {search ? (
                     loadingSearch ? (
                        <ActivityIndicator color={colors.tabActive} style={{ marginTop: 20 }} />
                     ) : searchResults.length > 0 ? (
                        searchResults.map((item, idx) => {
                           const isOld = dataOld.some((o: any) => o.idUser === item.idUser)
                           return (
                              <Pressable
                                 key={idx}
                                 style={[Styles.itemSelectModal, { borderColor: colors.icon + '20' }]}
                                 onPress={() => !isOld && handleToggleMember(item)}
                              >
                                 <View style={Styles.rowItemsCenter}>
                                    <ImageUser src={`${ConstEnv.url_storage}/files/${item.img}`} border />
                                    <View style={Styles.ml10}>
                                       <Text style={Styles.textDefault}>{item.name}</Text>
                                       {isOld && (
                                          <Text style={[Styles.textInformation, { color: colors.dimmed }]}>sudah menjadi anggota</Text>
                                       )}
                                    </View>
                                 </View>
                                 {selectMember.some(s => s.idUser === item.idUser) && (
                                    <AntDesign name="check" size={18} color={colors.tabActive} />
                                 )}
                              </Pressable>
                           )
                        })
                     ) : (
                        <Text style={[Styles.textDefault, { textAlign: 'center', color: colors.dimmed, marginTop: 20 }]}>
                           Tidak ada hasil
                        </Text>
                     )
                  ) : loadingDivisions ? (
                     <ActivityIndicator color={colors.tabActive} style={{ marginTop: 20 }} />
                  ) : divisions.length > 0 ? (
                     divisions.map((division) => {
                        const eligible = division.members.filter(m => !dataOld.some((o: any) => o.idUser === m.idUser))
                        const selectedCount = eligible.filter(m => selectMember.some(s => s.idUser === m.idUser)).length
                        const allSelected = division.membersLoaded && eligible.length > 0 && selectedCount === eligible.length
                        const someSelected = selectedCount > 0 && !allSelected
                        const isLoadingThis = loadingIds.includes(division.id)

                        return (
                           <View key={division.id}>
                              <Pressable
                                 style={[Styles.itemSelectModal, { borderColor: colors.icon + '20' }]}
                                 onPress={() => handleTapDivision(division)}
                              >
                                 <View style={Styles.flex1}>
                                    <Text style={[Styles.textDefaultSemiBold, { color: colors.text }]}>{division.name}</Text>
                                    {division.membersLoaded && (
                                       <Text style={[Styles.textSmallSemiBold, { color: colors.dimmed }]}>
                                          {selectedCount > 0
                                             ? `${selectedCount} dari ${eligible.length} dipilih`
                                             : `${eligible.length} anggota`}
                                       </Text>
                                    )}
                                 </View>
                                 {isLoadingThis ? (
                                    <ActivityIndicator size="small" color={colors.dimmed} />
                                 ) : allSelected ? (
                                    <AntDesign name="checkcircle" size={18} color={colors.tabActive} />
                                 ) : someSelected ? (
                                    <AntDesign name="checkcircleo" size={18} color={colors.tabActive} />
                                 ) : null}
                                 <Pressable
                                    onPress={() => handleToggleExpand(division.id)}
                                    style={{ paddingLeft: 10 }}
                                    hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
                                 >
                                    <Ionicons
                                       name={division.expanded ? "chevron-up" : "chevron-down"}
                                       size={16}
                                       color={colors.dimmed}
                                    />
                                 </Pressable>
                              </Pressable>

                              {division.expanded && division.members.map((member, idx) => {
                                 const isOld = dataOld.some((o: any) => o.idUser === member.idUser)
                                 return (
                                    <Pressable
                                       key={idx}
                                       style={[Styles.itemSelectModal, { borderColor: colors.icon + '15' }]}
                                       onPress={() => !isOld && handleToggleMember(member)}
                                    >
                                       <View style={Styles.rowItemsCenter}>
                                          <ImageUser src={`${ConstEnv.url_storage}/files/${member.img}`} border />
                                          <View style={Styles.ml10}>
                                             <Text style={Styles.textDefault}>{member.name}</Text>
                                             {isOld && (
                                                <Text style={[Styles.textInformation, { color: colors.dimmed }]}>sudah menjadi anggota</Text>
                                             )}
                                          </View>
                                       </View>
                                       {!isOld && selectMember.some(s => s.idUser === member.idUser) && (
                                          <AntDesign name="check" size={18} color={colors.tabActive} />
                                       )}
                                    </Pressable>
                                 )
                              })}
                           </View>
                        )
                     })
                  ) : (
                     <Text style={[Styles.textDefault, { textAlign: 'center', color: colors.dimmed, marginTop: 20 }]}>
                        Tidak ada divisi
                     </Text>
                  )}
               </View>
            </ScrollView>
         </View>
      </>
   )
}
