import { Node, mergeAttributes } from '@tiptap/core'
import { ReactNodeViewRenderer, NodeViewWrapper, ReactNodeViewProps } from '@tiptap/react'
import { motion, AnimatePresence } from 'framer-motion'
import { useState } from 'react'
import { Check } from 'lucide-react'

interface CharacterAttributes {
  id: string | null;
  name: string;
  avatar: string;
  gender: string;
  age: string;
}

interface Role {
  name: string;
  url: string;
}

interface CharacterTokenOptions {
  roles?: Role[];
}

export function CharacterToken(props: ReactNodeViewProps) {
  const [showRoleList, setShowRoleList] = useState(false)
  const { name, avatar } = props.node.attrs as CharacterAttributes
  const extension = props.extension as Node<CharacterTokenOptions>
  const roles = extension.options.roles || []

  const handleRoleSelect = (role: Role) => {
    const { editor } = props;
    const pos = props.getPos();
    
    if (typeof pos === 'number') {
      const { tr } = editor.state;
      tr.setNodeMarkup(pos, undefined, {
        ...props.node.attrs,
        name: role.name,
        avatar: role.url,
      });
      editor.view.dispatch(tr);
    }
    
    setShowRoleList(false);
  }

  return (
    <NodeViewWrapper
      as="span"
      data-alt="character-token"
      contentEditable={false}
      className="relative inline text-blue-400 cursor-pointer hover:text-blue-300 transition-colors duration-200"
      onMouseLeave={() => setShowRoleList(false)}
      onMouseEnter={() => setShowRoleList(true)}
    >
      {name}

      <AnimatePresence>
        {showRoleList && (
          <motion.div
            data-alt="role-list"
            initial={{ opacity: 0, y: 4 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: 4 }}
            transition={{ duration: 0.2 }}
            className="absolute top-full left-0 mt-2 w-64 rounded-lg backdrop-blur-md bg-white/10 border border-white/20 p-2 z-50"
          >
            <div className="space-y-1">
              {roles.map((role) => {
                const isSelected = role.name === name;
                return (
                  <div
                    key={role.name}
                    data-alt="role-item"
                    className={`flex items-center gap-3 p-2 rounded-lg cursor-pointer transition-colors duration-200
                      ${isSelected ? 'bg-blue-500/20 text-blue-400' : 'hover:bg-white/5 text-gray-200'}`}
                    onClick={() => handleRoleSelect(role)}
                  >
                    <div className="relative">
                      <img
                        src={role.url}
                        alt={role.name}
                        className={`w-10 h-10 rounded-full border transition-all duration-200
                          ${isSelected ? 'border-blue-400 border-2' : 'border-white/20'}`}
                      />
                      {isSelected && (
                        <div className="absolute -top-1 -right-1 bg-blue-500 rounded-full p-0.5">
                          <Check className="w-3 h-3 text-white" />
                        </div>
                      )}
                    </div>
                    <span className="flex-1">{role.name}</span>
                  </div>
                );
              })}
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </NodeViewWrapper>
  )
}

export const CharacterTokenExtension = Node.create<CharacterTokenOptions>({
  name: 'characterToken',
  group: 'inline',
  inline: true,
  atom: true,

  addOptions() {
    return {
      roles: [],
    }
  },

  addAttributes() {
    return {
      id: { default: null },
      name: { default: '' },
      gender: { default: '' },
      age: { default: '' },
      avatar: { default: '' },
    };
  },

  parseHTML() {
    return [{ tag: 'character-token' }];
  },

  renderHTML({ HTMLAttributes }) {
    return ['character-token', mergeAttributes(HTMLAttributes)];
  },

  addNodeView() {
    return ReactNodeViewRenderer(CharacterToken);
  },
});