import { useState, useContext, useCallback, useEffect, useRef } from 'react'
import PropTypes from 'prop-types'
import {
  Card,
  Button,
  Space,
  Typography,
  Flex,
  Tag,
  Dropdown,
  Divider,
  Modal
} from 'antd'
import { CaretLeftFilled, LoadingOutlined } from '@ant-design/icons'
import PlusIcon from '../../Icons/PlusIcon'
import BinIcon from '../../Icons/BinIcon'
import PersonIcon from '../../Icons/PersonIcon'
import TimeDisplay from './TimeDisplay'
import MarkdownDisplay from './MarkdownDisplay'
import IdDisplay from './IdDisplay'
import MissingPlaceholder from './MissingPlaceholder'
import NewNote from '../Management/Notes/NewNote'
import { ApiServerContext } from '../context/ApiServerContext'
import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon'
import UserNotifierToggle from './UserNotifierToggle'
import { AuthContext } from '../context/AuthContext'
import { getModelByName } from '../../../database/ObjectModels'
import { useNavigate } from 'react-router-dom'

const { Text } = Typography

const NoteItem = ({
  note,
  showCard = true,
  showCreatedAt = true,
  showChildNotes = true,
  showActions = true,
  showInfo = true,
  showBody = true,
  showFooter = true,
  largeSpacing = false
}) => {
  const [childNotes, setChildNotes] = useState([])
  const noteModel = getModelByName('note')
  const infoAction = noteModel.actions.filter(
    (action) => action.name == 'info'
  )[0]
  const InfoIcon = infoAction.icon
  const [newNoteOpen, setNewNoteOpen] = useState(false)
  const [deleteNoteOpen, setDeleteNoteOpen] = useState(false)
  const [deleteNoteLoading, setDeleteNoteLoading] = useState(false)
  const [childNotesLoading, setChildNotesLoading] = useState(false)
  const [isExpanded, setIsExpanded] = useState(false)
  const subscribeToObjectTypeUpdatesRef = useRef(null)
  const navigate = useNavigate()

  const {
    deleteObject,
    fetchObjects,
    subscribeToObjectTypeUpdates,
    connected
  } = useContext(ApiServerContext)
  const { userProfile, token } = useContext(AuthContext)

  let transformValue = 'rotate(0deg)'
  if (isExpanded) {
    transformValue = 'rotate(-90deg)'
  }

  const handleNoteExpand = useCallback(async () => {
    setChildNotesLoading(true)
    try {
      const childNotesData = await fetchObjects('note', {
        filter: { 'parent._id': note._id }
      })
      setChildNotes(childNotesData.data)
    } catch (error) {
      console.error('Error fetching child notes:', error)
    } finally {
      setChildNotesLoading(false)
    }
  }, [note._id, fetchObjects])

  const toggleExpand = async () => {
    if (isExpanded == false) {
      await handleNoteExpand()
      setIsExpanded(true)
    } else {
      setChildNotes([])
      setIsExpanded(false)
    }
  }

  const handleDeleteNote = async () => {
    if (token != null) {
      setDeleteNoteLoading(true)
      await deleteObject(note._id, 'note')
      setDeleteNoteOpen(false)
      setDeleteNoteLoading(false)
    }
  }

  useEffect(() => {
    if (connected == true && subscribeToObjectTypeUpdatesRef.current == null) {
      if (isExpanded == true) {
        subscribeToObjectTypeUpdatesRef.current = subscribeToObjectTypeUpdates(
          'note',
          { 'parent._id': note._id },
          () => {
            if (isExpanded == true) {
              handleNoteExpand()
            }
          }
        )
      } else {
        if (subscribeToObjectTypeUpdatesRef.current) {
          subscribeToObjectTypeUpdatesRef.current()
          subscribeToObjectTypeUpdatesRef.current = null
        }
      }
    }

    return () => {
      if (connected == true && subscribeToObjectTypeUpdatesRef.current) {
        subscribeToObjectTypeUpdatesRef.current()
        subscribeToObjectTypeUpdatesRef.current = null
      }
    }
  }, [
    subscribeToObjectTypeUpdates,
    connected,
    handleNoteExpand,
    isExpanded,
    note._id
  ])

  // Check if the current user can delete this note
  const canDeleteNote = userProfile && userProfile._id === note.user._id

  const dropdownItems = [
    {
      key: 'new',
      icon: <PlusIcon />,
      label: 'New Note',
      onClick: () => {
        setNewNoteOpen(true)
      }
    }
  ]

  // Only add delete option if user owns the note
  if (canDeleteNote) {
    dropdownItems.push({
      key: 'delete',
      label: 'Delete Note',
      icon: <BinIcon />,
      onClick: () => {
        setDeleteNoteOpen(true)
      },
      danger: true
    })
  }

  const noteItem = (
    <>
      <Flex vertical gap={'small'}>
        {showBody && (
          <Flex gap={'middle'} align='start' style={{ marginBottom: '4px' }}>
            <Space>
              <PersonIcon />
              <Text style={{ whiteSpace: 'nowrap' }}>{note.user.name}:</Text>
            </Space>
            <div style={{ marginTop: '1px' }}>
              <MarkdownDisplay content={note.content} />
            </div>
          </Flex>
        )}
        {showFooter && showBody && (
          <Divider style={{ margin: largeSpacing ? '10px 0' : 0 }} />
        )}
        {showFooter && (
          <Flex wrap gap={'small'}>
            {showActions && (
              <>
                <Dropdown
                  menu={{ items: dropdownItems }}
                  trigger={['hover']}
                  placement='bottomLeft'
                >
                  <Button size='small'>Actions</Button>
                </Dropdown>
                <UserNotifierToggle
                  type='note'
                  size='small'
                  objectData={note}
                  disabled={false}
                />
              </>
            )}
            <Space size={'small'} style={{ marginRight: 8 }}>
              <Text type='secondary'>Type:</Text>
              <Tag color={note.noteType.color} style={{ margin: 0 }}>
                {note.noteType.name}
              </Tag>
            </Space>
            <Space size={'small'} style={{ marginRight: 8 }}>
              <Text type='secondary'>User ID:</Text>
              <IdDisplay
                longId={false}
                id={note.user._id}
                type={'user'}
                showHyperlink={true}
              />
            </Space>
            {showCreatedAt && (
              <Space size={'small'} style={{ marginRight: 8 }}>
                <Text type='secondary'>Created At:</Text>
                <TimeDisplay dateTime={note.createdAt} showSince={true} />
              </Space>
            )}
            <Flex style={{ flexGrow: 1 }} justify='end'>
              <Space size={'small'}>
                {showInfo && (
                  <Button
                    icon={<InfoIcon />}
                    type='text'
                    size='small'
                    onClick={() => {
                      navigate(infoAction.url(note._id))
                    }}
                  />
                )}
                {showChildNotes && (
                  <Button
                    icon={
                      childNotesLoading ? (
                        <LoadingOutlined />
                      ) : (
                        <CaretLeftFilled />
                      )
                    }
                    size='small'
                    type='text'
                    loading={childNotesLoading}
                    disabled={childNotesLoading}
                    style={{
                      transform: transformValue,
                      transition: 'transform 0.2s ease'
                    }}
                    onClick={toggleExpand}
                  />
                )}
              </Space>
            </Flex>
          </Flex>
        )}
        {isExpanded && (
          <Flex vertical gap={'small'} style={{ flexGrow: 1 }}>
            {childNotes.length > 0 ? (
              childNotes.map((childNote) => (
                <NoteItem key={childNote._id} note={childNote} />
              ))
            ) : (
              <MissingPlaceholder message={'No child notes.'} />
            )}
          </Flex>
        )}
        <Flex vertical gap={'middle'}></Flex>
      </Flex>
      <Modal
        open={newNoteOpen}
        onCancel={() => {
          setNewNoteOpen(false)
        }}
        width={800}
        destroyOnHidden={true}
        footer={null}
      >
        <NewNote
          onOk={() => {
            setNewNoteOpen(false)
          }}
          defaultValues={{
            parent: { _id: note._id },
            parentType: 'note'
          }}
        />
      </Modal>
      <Modal
        open={deleteNoteOpen}
        title={
          <Space size={'middle'}>
            <ExclamationOctagonIcon />
            Confirm Delete
          </Space>
        }
        okText='Delete'
        cancelText='Cancel'
        okType='danger'
        closable={false}
        centered
        maskClosable={false}
        footer={[
          <Button
            key='cancel'
            onClick={() => {
              setDeleteNoteOpen(false)
            }}
            disabled={deleteNoteLoading}
          >
            Cancel
          </Button>,
          <Button
            key='delete'
            type='primary'
            danger
            onClick={handleDeleteNote}
            loading={deleteNoteLoading}
            disabled={deleteNoteLoading}
          >
            Delete
          </Button>
        ]}
      >
        <Text>Are you sure you want to delete this note?</Text>
      </Modal>
    </>
  )

  return showCard ? (
    <Card
      key={note._id}
      size='small'
      style={{
        backgroundColor: note.noteType.color + '26',
        textAlign: 'left'
      }}
    >
      {noteItem}
    </Card>
  ) : (
    noteItem
  )
}

NoteItem.propTypes = {
  note: PropTypes.object.isRequired,
  showCard: PropTypes.bool,
  showCreatedAt: PropTypes.bool,
  showChildNotes: PropTypes.bool,
  showActions: PropTypes.bool,
  largeSpacing: PropTypes.bool,
  showInfo: PropTypes.bool,
  showBody: PropTypes.bool,
  showFooter: PropTypes.bool
}

export default NoteItem
