import { useCallback, useContext, useEffect, useState, useRef } from 'react'
import PropTypes from 'prop-types'
import {
  Card,
  Button,
  Space,
  Typography,
  Flex,
  Modal,
  Spin,
  Alert,
  Dropdown
} from 'antd'
import { LoadingOutlined } from '@ant-design/icons'
import PlusIcon from '../../Icons/PlusIcon'
import { AuthContext } from '../context/AuthContext'
import { ApiServerContext } from '../context/ApiServerContext'
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
import ReloadIcon from '../../Icons/ReloadIcon'
import NewNote from '../Management/Notes/NewNote'
import NoteItem from './NoteItem'

const { Text } = Typography

const NotesPanel = ({ _id, type }) => {
  const [newNoteOpen, setNewNoteOpen] = useState(false)
  const [loading, setLoading] = useState(true)
  const [initialized, setInitialized] = useState(false)
  const [error, setError] = useState(null)
  const [notes, setNotes] = useState(null)
  const [expandedNotes, setExpandedNotes] = useState({})
  const subscribeToObjectTypeUpdatesRef = useRef(null)

  const { token } = useContext(AuthContext)
  const { fetchNotes, connected, subscribeToObjectTypeUpdates } =
    useContext(ApiServerContext)

  const fetchData = useCallback(
    async (id) => {
      try {
        const newData = await fetchNotes(id)
        return newData
      } catch (error) {
        setError(error)
        return null
      }
    },
    [fetchNotes]
  )

  const generateNotes = useCallback(
    async (id) => {
      const notesData = await fetchData(id)
      setLoading(false)

      if (notesData == null) {
        return null
      }

      if (notesData.length <= 0) {
        return (
          <Card>
            <Flex
              justify='center'
              gap={'small'}
              style={{ height: '100%' }}
              align='center'
            >
              <Text type='secondary'>
                <InfoCircleIcon />
              </Text>
              <Text type='secondary'>No notes added.</Text>
            </Flex>
          </Card>
        )
      }

      return notesData.map((note) => (
        <NoteItem
          key={note._id}
          note={note}
          expandedNotes={expandedNotes}
          setExpandedNotes={setExpandedNotes}
        />
      ))
    },
    [fetchData, expandedNotes]
  )

  const handleReloadData = useCallback(async () => {
    setNotes(await generateNotes(_id))
  }, [_id, generateNotes])

  useEffect(() => {
    if (connected == true && subscribeToObjectTypeUpdatesRef.current == null) {
      subscribeToObjectTypeUpdatesRef.current = subscribeToObjectTypeUpdates(
        'note',
        (noteData) => {
          if (noteData.parent._id == _id) {
            handleReloadData()
          }
        }
      )
    }
    return () => {
      if (connected == true && subscribeToObjectTypeUpdatesRef.current) {
        subscribeToObjectTypeUpdatesRef.current()
        subscribeToObjectTypeUpdatesRef.current = null
      }
    }
  }, [_id, subscribeToObjectTypeUpdates, connected, handleReloadData])

  useEffect(() => {
    if (connected == true && token != null && !initialized) {
      handleReloadData()
      setInitialized(true)
    }
  }, [token, handleReloadData, initialized, connected])

  const actionItems = {
    items: [
      {
        label: 'New Note',
        key: 'newNote',
        icon: <PlusIcon />
      },
      { type: 'divider' },
      {
        label: 'Reload Notes',
        key: 'reloadNotes',
        icon: <ReloadIcon />
      }
    ],
    onClick: ({ key }) => {
      if (key === 'reloadNotes') {
        setLoading(true)
        handleReloadData()
      } else if (key === 'newNote') {
        setNewNoteOpen(true)
      }
    }
  }

  return (
    <Flex vertical gap='large' style={{ width: '100%' }}>
      <Flex justify='space-between'>
        <Space size={'small'}>
          <Dropdown menu={actionItems} disabled={loading}>
            <Button disabled={loading}>Actions</Button>
          </Dropdown>
        </Space>
        <Space size={'small'}>
          <Button
            type='primary'
            icon={<PlusIcon />}
            disabled={loading}
            onClick={() => {
              setNewNoteOpen(true)
            }}
          />
        </Space>
      </Flex>

      <Space direction='vertical' size='middle' style={{ width: '100%' }}>
        <Spin indicator={<LoadingOutlined />} spinning={loading}>
          {error ? (
            <Alert message={error?.message} type='error' showIcon={true} />
          ) : (
            <Flex vertical gap={'middle'}>
              {notes}
            </Flex>
          )}
        </Spin>
      </Space>

      <Modal
        open={newNoteOpen}
        width={800}
        destroyOnHidden={true}
        footer={null}
        onCancel={() => {
          setNewNoteOpen(false)
        }}
      >
        <NewNote
          onOk={() => {
            setNewNoteOpen(false)
          }}
          reset={newNoteOpen}
          defaultValues={{
            parent: { _id },
            parentType: type
          }}
        />
      </Modal>
    </Flex>
  )
}

NotesPanel.propTypes = {
  _id: PropTypes.string.isRequired,
  type: PropTypes.string.isRequired,
  onNewNote: PropTypes.func
}

export default NotesPanel
