import AdaptableCard from '@/components/shared/AdaptableCard'
import Container from '@/components/shared/Container'
import Drawer from '@/components/ui/Drawer'
import Button from '@/components/ui/Button'
import NotificationChannels from '@/constants/notification-channel.enum'
import { NotificationDto } from '@/proxy/notification/models'
import { getList } from '@/services/notification.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import dayjs from 'dayjs'
import { groupBy } from '@/utils/collection'
import { useCallback, useEffect, useState } from 'react'
import Log from './components/Log'
import LogFilter from './components/LogFilter'
import PageTitle from '@/components/shared/PageTitle'
import { DIR_RTL } from '@/constants/theme.constant'
import { useStoreState } from '@/store'

const itemsPerPage = 10
type NotificationGroups = Record<string, NotificationDto[]>

const ActivityLog = () => {
  const { translate } = useLocalization()

  const [loading, setLoading] = useState(false)
  const [notifications, setNotifications] = useState<NotificationGroups>({})
  const [page, setPage] = useState(0)
  const [hasMore, setHasMore] = useState(false)
  const [isFilterDrawerOpen, setIsFilterDrawerOpen] = useState(false)
  const direction = useStoreState((state) => state.theme.direction)
  const [filter, setFilter] = useState<string[]>([
    NotificationChannels.Desktop,
    NotificationChannels.Mail,
    NotificationChannels.Rocket,
    NotificationChannels.Sms,
    NotificationChannels.UiActivity,
    NotificationChannels.UiToast,
    NotificationChannels.WhatsApp,
    NotificationChannels.Telegram,
  ])

  const fetchData = useCallback(async (isLoadmore: boolean = false) => {
    setLoading(true)
    try {
      const response = await getList({
        maxResultCount: itemsPerPage,
        skipCount: page * itemsPerPage,
        sorting: 'CreationTime DESC',
        channels: filter,
        isListRequest: true,
      })
      const items = response.data?.items ?? []

      const currentItemCount = page * itemsPerPage + items.length
      setHasMore((response.data?.totalCount ?? 0) > currentItemCount)
      const logs = groupBy(items, (a) => dayjs(a.creationTime).format('YYYY-MM-DD'))

      if (isLoadmore) {
        setNotifications((prev) => {
          const next: NotificationGroups = { ...prev }

          for (const [key, value] of Object.entries(logs)) {
            next[key] = [...(next[key] ?? []), ...value]
          }

          return next
        })
      } else {
        setNotifications(logs)
      }
    } finally {
      setLoading(false)
    }
  }, [filter, page])

  useEffect(() => {
    fetchData(page > 0)
  }, [fetchData, page])

  const handleFilterChange = (value: string[]) => {
    setPage(0)
    setNotifications({})
    setHasMore(false)
    setFilter(value)
    setIsFilterDrawerOpen(false)
  }

  return (
    <Container>
      <PageTitle title={translate('::' + 'Abp.Identity.ActivityLogs')} />

      <AdaptableCard className="overflow-hidden bg-white dark:bg-gray-800">
        <div className="w-full">
          <div className="mb-5 flex items-center justify-between gap-3">
            <h3 className="text-xl font-semibold md:text-2xl text-gray-900 dark:text-white">
              {translate('::Abp.Identity.ActivityLogs')}
            </h3>
            <Button
              className="lg:hidden dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600"
              size="sm"
              variant="twoTone"
              onClick={() => setIsFilterDrawerOpen(true)}
            >
              {translate('::Abp.Identity.ActivityLogs.Filters')}
            </Button>
          </div>

          <div className="grid grid-cols-1 gap-6 lg:grid-cols-[minmax(0,1fr)_340px]">
            <div className="min-w-0 rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-4 lg:p-6">
              <Log
                notifications={notifications}
                isLoading={loading}
                loadable={hasMore}
                onLoadMore={() => setPage((prev) => prev + 1)}
              ></Log>
            </div>

            <div className="hidden lg:block">
              <LogFilter useAffix filter={filter} className="dark:bg-gray-800" onFilterChange={handleFilterChange} />
            </div>
          </div>
        </div>

        <Drawer
          title={translate('::Abp.Identity.ActivityLogs.Filters')}
          isOpen={isFilterDrawerOpen}
          width={340}
          placement={direction === DIR_RTL ? 'right' : 'left'}
          onClose={() => setIsFilterDrawerOpen(false)}
          onRequestClose={() => setIsFilterDrawerOpen(false)}
        >
          <LogFilter
            filter={filter}
            useAffix={false}
            className="border-none p-0 dark:bg-gray-800"
            onFilterChange={handleFilterChange}
          />
        </Drawer>
      </AdaptableCard>
    </Container>
  )
}

export default ActivityLog
