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,
  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',
          (noteData) => {
            if (noteData.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'}>
        <Flex gap={'middle'} align='start'>
          <Space>
            <PersonIcon />
            <Text style={{ whiteSpace: 'nowrap' }}>{note.user.name}:</Text>
          </Space>
          <div style={{ marginBottom: '4px' }}>
            <MarkdownDisplay content={note.content} />
          </div>
        </Flex>
        <Divider style={{ margin: largeSpacing ? '10px 0' : 0 }} />
        <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}
        closeIcon={false}
        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
}

export default NoteItem
