'use client'

import React, { useCallback, useEffect, useState } from 'react'
import {
  Button,
  Dropdown,
  DropdownHeader,
  DropdownItem,
  Spinner,
} from 'flowbite-react'
import { FiBell, FiCheck } from 'react-icons/fi'
import { useRouter } from 'next/navigation'
import { formatDistanceToNow } from 'date-fns'
import { AxiosError } from 'axios'
import { toast } from 'react-toastify'

import buttonTheme from '@/lib/themes/button'
import dropdownTheme from '@/lib/themes/dropdown'
import { useNotifications } from '@/lib/context/NotificationContext'
import {
  getAllNotifications,
  markAllAsRead,
} from '@/lib/services/notification-services'
import * as PaginationConstant from '@/lib/constants/pagination'
import { Notification } from '@/lib/types/notification'
import { handleApiError } from '@/lib/utils/error-handler'

export default function NotificationDropdown() {
  const router = useRouter()
  const [notifications, setNotifications] = useState<Notification[]>([])
  const [isLoading, setIsLoading] = useState(true)
  const [isMarkingAllAsRead, setIsMarkingAllAsRead] = useState(false)
  const {
    unreadCount,
    refreshTrigger,
    readNotificationId,
    deletedNotificationId,
    isLoading: isLoadingNotificationCount,
    goToActionDetail,
    refreshNotifications,
  } = useNotifications()

  const fetchNotifications = useCallback(async () => {
    try {
      setIsLoading(true)

      const notifications = await getAllNotifications({
        page: 1,
        limit: PaginationConstant.MIN_DATA_PER_PAGE,
        type: 'all',
      })

      setNotifications(notifications.data)
    } catch (error) {
      if (error instanceof AxiosError) {
        toast.error(error.response?.data?.message)
      }
    } finally {
      setIsLoading(false)
    }
  }, [])

  async function handleMarkAllAsRead() {
    try {
      setIsMarkingAllAsRead(true)

      await markAllAsRead()

      // Refresh notifications to make sure unread count update on other components.
      refreshNotifications()
    } catch (error) {
      handleApiError(error, 'Failed to mark all as read')
    } finally {
      setIsMarkingAllAsRead(false)
    }
  }

  useEffect(() => {
    fetchNotifications()
  }, [refreshTrigger, fetchNotifications])

  useEffect(() => {
    if (readNotificationId) {
      setNotifications((prev) =>
        prev.map((notification) =>
          notification.id === readNotificationId
            ? {
                ...notification,
                is_read: true,
                read_at: new Date().toISOString(),
              }
            : notification,
        ),
      )
    }

    if (deletedNotificationId) {
      const updatedNotifications = notifications.filter(
        (notification) => notification.id !== deletedNotificationId,
      )

      if (updatedNotifications.length < PaginationConstant.MIN_DATA_PER_PAGE) {
        // Refetch notifications to fill up the list if needed
        fetchNotifications()
      }
    }
  }, [
    readNotificationId,
    deletedNotificationId,
    notifications,
    fetchNotifications,
  ])

  return (
    <Dropdown
      arrowIcon={false}
      color="alternative"
      theme={{
        ...dropdownTheme.dropdown,
        floating: {
          ...dropdownTheme.dropdown.floating,
          target: `${dropdownTheme.dropdown.floating.target} px-0`,
        },
      }}
      placement="bottom-end"
      label={
        <div className="relative w-10 h-10 flex items-center justify-center">
          <FiBell className="h-5 w-5" />

          {unreadCount > 0 && !isLoadingNotificationCount && (
            <span className="absolute -top-1 -right-1 bg-red-500 text-white text-[10px] rounded-full h-5 w-5 flex items-center justify-center">
              {unreadCount > 99 ? '99+' : unreadCount}
            </span>
          )}
        </div>
      }
    >
      <DropdownHeader>
        <div className="flex items-center justify-between">
          <span className="text-sm font-medium">Notifications</span>
          {unreadCount > 0 && (
            <Button
              color="alternative"
              className="text-green-500 hover:text-green-700 focus:ring-0"
              size="xs"
              theme={buttonTheme.button}
              onClick={handleMarkAllAsRead}
            >
              {isMarkingAllAsRead ? (
                <React.Fragment>
                  <Spinner size="sm" light className="mr-1" />
                  Marking...
                </React.Fragment>
              ) : (
                <React.Fragment>
                  <FiCheck className="w-3 h-3 mr-1" />
                  Mark all read
                </React.Fragment>
              )}
            </Button>
          )}
        </div>
      </DropdownHeader>

      {isLoading ? (
        <div className="px-4 py-3">
          <div className="animate-pulse space-y-2 min-w-3xs">
            {[...Array(3)].map((_, index) => (
              <div key={index} className="flex items-center space-x-2 w-64">
                <div className="w-8 h-8 bg-gray-200 rounded-full"></div>
                <div className="flex-1 space-y-1">
                  <div className="h-3 bg-gray-200 rounded w-3/4"></div>
                  <div className="h-2 bg-gray-200 rounded w-1/2"></div>
                </div>
              </div>
            ))}
          </div>
        </div>
      ) : notifications.length === 0 ? (
        <div className="px-4 py-6 text-center text-gray-500 min-w-3xs">
          <FiBell className="w-8 h-8 mx-auto mb-2 text-gray-400" />
          <p className="text-sm">No notifications</p>
        </div>
      ) : (
        <React.Fragment>
          <div className="max-h-96 overflow-y-auto">
            {notifications.map((notification, index) => (
              <DropdownItem
                key={index}
                onClick={() => goToActionDetail(notification)}
                className={`px-4 py-3 border-b border-gray-200  ${
                  !notification.is_read ? 'bg-slate-50' : ''
                }`}
              >
                <div className="flex items-start space-x-3">
                  <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-1 mb-1">
                      <p className="text-sm font-medium text-gray-900 truncate">
                        {notification.formatted_type}
                      </p>
                      {!notification.is_read && (
                        <span className="w-2 h-2 bg-blue-500 rounded-full ml-2"></span>
                      )}
                    </div>
                    <p className="text-xs text-left text-gray-600 line-clamp-2 mb-1 max-w-xs">
                      {notification.message}
                    </p>
                    <p className="text-xs text-gray-400 w-fit">
                      {formatDistanceToNow(new Date(notification.created_at), {
                        addSuffix: true,
                      })}
                    </p>
                  </div>
                </div>
              </DropdownItem>
            ))}
          </div>

          {notifications.length > 0 && (
            <DropdownItem
              onClick={() => router.push('/notifications')}
              className="text-center text-blue-600 hover:text-blue-700"
            >
              View all notifications
            </DropdownItem>
          )}
        </React.Fragment>
      )}
    </Dropdown>
  )
}
