import Link from '@tiptap/extension-link'
import { EditorProvider, useCurrentEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import React from 'react'
import '../styles/styles.css'
import '../styles/tiptap.scss'

interface InputFieldProps {
  label: string
  description?: string
  type?: 'text' | 'textarea' | 'richtext'
  placeholder: string
  name: string
  inputMode?: 'url'
  value: string
  error?: string
  onChange: (name: string, value: string) => void
}

export const InputField = React.memo(
  ({
    label,
    description,
    type = 'text',
    placeholder,
    name,
    inputMode,
    value,
    error,
    onChange
  }: InputFieldProps) => {
    const handleChange = (
      e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
    ) => {
      onChange(name, e.target.value)
    }

    return (
      <div className='inputLabelWrapperMain'>
        <label className='form-label labelMain'>{label}</label>
        {description && <p className='labelDescriptionMain'>{description}</p>}
        {type === 'textarea' ? (
          <textarea
            className='inputMain'
            placeholder={placeholder}
            name={name}
            value={value}
            onChange={handleChange}
          ></textarea>
        ) : type === 'richtext' ? (
          <RichTextEditor
            content={value}
            updateContent={(content) => onChange(name, content)}
          />
        ) : (
          <input
            type={type}
            className='inputMain'
            placeholder={placeholder}
            name={name}
            inputMode={inputMode}
            value={value}
            onChange={handleChange}
          />
        )}
        {error && <InputError message={error} />}
      </div>
    )
  }
)

type InputErrorProps = {
  message: string
}

export const InputError = ({ message }: InputErrorProps) => {
  if (!message) return null

  return (
    <div className='errorMain'>
      <div className='errorMainColor'></div>
      <p className='errorMainText'>{message}</p>
    </div>
  )
}

interface CheckboxFieldProps {
  label: string
  name: string
  isChecked: boolean
  handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void
}

export const CheckboxField = React.memo(
  ({ label, name, isChecked, handleChange }: CheckboxFieldProps) => (
    <div className='inputLabelWrapperMain inputLabelWrapperMainAlt inputLabelWrapperMainAltStylized'>
      <label className='form-label labelMain'>{label}</label>
      <input
        type='checkbox'
        className='CheckboxMain'
        name={name}
        checked={isChecked}
        onChange={handleChange}
      />
    </div>
  )
)

type RichTextEditorProps = {
  content: string
  updateContent: (updatedContent: string) => void
}

const RichTextEditor = ({ content, updateContent }: RichTextEditorProps) => {
  return (
    <div className='inputMain'>
      <EditorProvider
        slotBefore={<MenuBar />}
        extensions={[StarterKit, Link]}
        content={content}
        onUpdate={({ editor }) => {
          // Update the state when the editor content changes
          updateContent(editor.getHTML())
        }}
      ></EditorProvider>
    </div>
  )
}

const MenuBar = () => {
  const { editor } = useCurrentEditor()

  if (!editor) {
    return null
  }

  const setLink = () => {
    const url = prompt('URL')
    if (url) {
      return editor.chain().focus().setLink({ href: url }).run()
    }

    return false
  }

  const unsetLink = () => editor.chain().focus().unsetLink().run()

  const buttons: MenuBarButtonProps[] = [
    {
      label: 'Bold',
      disabled: !editor.can().chain().focus().toggleBold().run(),
      isActive: editor.isActive('bold'),
      onClick: () => editor.chain().focus().toggleBold().run()
    },
    {
      label: 'Italic',
      disabled: !editor.can().chain().focus().toggleItalic().run(),
      isActive: editor.isActive('italic'),
      onClick: () => editor.chain().focus().toggleItalic().run()
    },
    {
      label: 'Strike',
      disabled: !editor.can().chain().focus().toggleStrike().run(),
      isActive: editor.isActive('strike'),
      onClick: () => editor.chain().focus().toggleStrike().run()
    },
    {
      label: 'Clear marks',
      onClick: () => editor.chain().focus().unsetAllMarks().run()
    },
    {
      label: 'Clear nodes',
      onClick: () => editor.chain().focus().clearNodes().run()
    },
    {
      label: 'Paragraph',
      isActive: editor.isActive('paragraph'),
      onClick: () => editor.chain().focus().toggleStrike().run()
    },
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    ...[1, 2, 3, 4, 5, 6].map((level: any) => ({
      label: `H${level}`,
      isActive: editor.isActive('heading', { level }),
      onClick: () => editor.chain().focus().toggleHeading({ level }).run()
    })),
    {
      label: 'Bullet list',
      isActive: editor.isActive('bulletList'),
      onClick: () => editor.chain().focus().toggleBulletList().run()
    },
    {
      label: 'Ordered list',
      isActive: editor.isActive('orderedList'),
      onClick: () => editor.chain().focus().toggleOrderedList().run()
    },
    {
      label: 'Code block',
      isActive: editor.isActive('codeBlock'),
      onClick: () => editor.chain().focus().toggleCodeBlock().run()
    },
    {
      label: 'Blockquote',
      isActive: editor.isActive('blockquote'),
      onClick: () => editor.chain().focus().toggleBlockquote().run()
    },
    {
      label: 'Link',
      isActive: editor.isActive('link'),
      onClick: editor.isActive('link') ? unsetLink : setLink
    },
    {
      label: 'Horizontal rule',
      onClick: () => editor.chain().focus().setHorizontalRule().run()
    },
    {
      label: 'Hard break',
      onClick: () => editor.chain().focus().setHardBreak().run()
    },
    {
      label: 'Undo',
      disabled: !editor.can().chain().focus().undo().run(),
      onClick: () => editor.chain().focus().undo().run()
    },
    {
      label: 'Redo',
      disabled: !editor.can().chain().focus().redo().run(),
      onClick: () => editor.chain().focus().redo().run()
    }
  ]

  return (
    <div className='control-group'>
      <div className='button-group'>
        {buttons.map(({ label, disabled, isActive, onClick }) => (
          <MenuBarButton
            key={label}
            label={label}
            disabled={disabled}
            isActive={isActive}
            onClick={onClick}
          />
        ))}
      </div>
    </div>
  )
}

interface MenuBarButtonProps {
  label: string
  isActive?: boolean
  disabled?: boolean
  onClick: () => boolean
}

const MenuBarButton = ({
  label,
  isActive = false,
  disabled = false,
  onClick
}: MenuBarButtonProps) => (
  <button
    onClick={onClick}
    disabled={disabled}
    className={`btn btnMain btnMainTipTap ${isActive ? 'is-active' : ''}`}
  >
    {label}
  </button>
)
