import PropTypes from 'prop-types'
import { useState, useEffect, useContext } from 'react'
import { Button, message, Popover, Typography, Space, Flex } from 'antd'
import { UserOutlined } from '@ant-design/icons'
import BellIcon from '../../Icons/BellIcon'
import NewMailIcon from '../../Icons/NewMailIcon'
import { ApiServerContext } from '../context/ApiServerContext'
import { AuthContext } from '../context/AuthContext'
import { LoadingOutlined } from '@ant-design/icons'
import InfoCircleIcon from '../../Icons/InfoCircleIcon'

const { Text } = Typography

const UserNotifierToggle = ({
  type,
  objectData,
  disabled = false,
  ...buttonProps
}) => {
  const {
    toggleUserNotifier,
    editUserNotifier,
    fetchUserNotifiersForObject,
    fetchAllUserNotifiersForObject
  } = useContext(ApiServerContext)
  const { userProfile } = useContext(AuthContext)
  const [isNotifying, setIsNotifying] = useState(false)
  const [loading, setLoading] = useState(false)
  const [initialLoad, setInitialLoad] = useState(true)
  const [allNotifiers, setAllNotifiers] = useState([])
  const [popoverOpen, setPopoverOpen] = useState(false)
  const [popoverLoading, setPopoverLoading] = useState(false)
  const [emailTogglingId, setEmailTogglingId] = useState(null)

  const objectId = objectData?._id

  useEffect(() => {
    const loadNotifierState = async () => {
      if (!objectId || !type) return

      setInitialLoad(true)
      try {
        const { data } = await fetchUserNotifiersForObject(objectId, type)
        setIsNotifying(data?.length > 0)
      } catch (error) {
        console.error('Error fetching user notifier state:', error)
      } finally {
        setInitialLoad(false)
      }
    }

    loadNotifierState()
  }, [objectId, type, fetchUserNotifiersForObject])

  useEffect(() => {
    const loadAllNotifiers = async () => {
      if (!objectId || !type || !popoverOpen) return

      setPopoverLoading(true)
      try {
        const { data } = await fetchAllUserNotifiersForObject(objectId, type)
        setAllNotifiers(data || [])
      } catch (error) {
        console.error('Error fetching all user notifiers:', error)
        setAllNotifiers([])
      } finally {
        setPopoverLoading(false)
      }
    }

    loadAllNotifiers()
  }, [objectId, type, popoverOpen, fetchAllUserNotifiersForObject])

  const handleClick = async () => {
    if (!objectId || !type || loading) return

    setLoading(true)
    try {
      const enabled = await toggleUserNotifier(objectId, type)
      setIsNotifying(enabled)
      if (popoverOpen) {
        const { data } = await fetchAllUserNotifiersForObject(objectId, type)
        setAllNotifiers(data || [])
      }
      message.success(
        enabled
          ? 'Notifications enabled for this object'
          : 'Notifications disabled for this object'
      )
    } catch (error) {
      console.error('Error toggling user notifier:', error)
      message.error('Failed to update notifications')
    } finally {
      setLoading(false)
    }
  }

  const getUserDisplayName = (user) => {
    if (!user) return 'Unknown'
    return (
      user.name ||
      user.username ||
      `${user.firstName || ''} ${user.lastName || ''}`.trim() ||
      user.email ||
      'Unknown'
    )
  }

  const isCurrentUser = (user) => user?._id === userProfile?._id

  const handleEmailToggle = async (item) => {
    if (!isCurrentUser(item.user) || emailTogglingId) return
    setEmailTogglingId(item._id)
    const newEmail = !item.email
    try {
      const result = await editUserNotifier(item._id, { email: newEmail })
      if (result) {
        setAllNotifiers((prev) =>
          prev.map((n) =>
            n._id === item._id ? { ...n, email: result.email ?? newEmail } : n
          )
        )
        message.success(
          (result.email ?? newEmail)
            ? 'Email notifications enabled'
            : 'Email notifications disabled'
        )
      }
    } catch (error) {
      console.error('Error toggling email:', error)
      message.error('Failed to update email notifications')
    } finally {
      setEmailTogglingId(null)
    }
  }

  const popoverContent = (
    <Flex
      vertical
      justify='center'
      style={{ minWidth: 240, minHeight: 25 }}
      gap={'4px'}
    >
      {popoverLoading ? (
        <Space size={'small'}>
          <LoadingOutlined />
          <Text style={{ margin: 0 }}>Loading, please wait...</Text>
        </Space>
      ) : allNotifiers.length === 0 ? (
        <Space size={'small'}>
          <Text style={{ margin: 0 }} type='secondary'>
            <InfoCircleIcon />
          </Text>
          <Text style={{ margin: 0 }} type='secondary'>
            No users subscribed.
          </Text>
        </Space>
      ) : (
        <>
          {[...allNotifiers]
            .sort(
              (a, b) =>
                (isCurrentUser(b.user) ? 1 : 0) -
                (isCurrentUser(a.user) ? 1 : 0)
            )
            .map((item) => (
              <Flex key={item._id} justify='space-between' align='center'>
                <Flex align='center' gap={'6px'}>
                  <UserOutlined />
                  <Text>{getUserDisplayName(item.user)}</Text>
                  {isCurrentUser(item.user) && (
                    <Text type='secondary'> (you)</Text>
                  )}
                </Flex>
                <Space size={'small'}>
                  <Button
                    type='text'
                    icon={
                      <NewMailIcon
                        style={{
                          color: item.email ? 'var(--color-primary)' : undefined
                        }}
                      />
                    }
                    size='small'
                    disabled={!isCurrentUser(item.user)}
                    loading={emailTogglingId === item._id}
                    onClick={() => handleEmailToggle(item)}
                  />
                </Space>
              </Flex>
            ))}
        </>
      )}
    </Flex>
  )

  return (
    <Popover
      content={popoverContent}
      title={null}
      trigger='hover'
      placement='bottomLeft'
      arrow={false}
      open={popoverOpen}
      onOpenChange={setPopoverOpen}
      styles={{ body: { padding: '10px 15px' } }}
    >
      <Button
        {...buttonProps}
        icon={
          <BellIcon
            style={{
              color: isNotifying ? 'var(--color-warning)' : undefined
            }}
          />
        }
        disabled={disabled || loading || initialLoad}
        loading={loading || !objectId || !type}
        onClick={handleClick}
      />
    </Popover>
  )
}

UserNotifierToggle.propTypes = {
  type: PropTypes.string.isRequired,
  objectData: PropTypes.object.isRequired,
  disabled: PropTypes.bool
}

export default UserNotifierToggle
