import Link from '@tiptap/extension-link';
import Underline from '@tiptap/extension-underline';
import { EditorContent, useEditor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import {
    Bold,
    Code2,
    Italic,
    Link2,
    Link2Off,
    List,
    ListOrdered,
    Underline as UnderlineIcon,
} from 'lucide-react';
import { useEffect, useState } from 'react';

type Props = {
    value: string;
    onChange: (html: string) => void;
    placeholder?: string;
    /** Adds a toggle to edit the raw HTML source instead of the rich text view. */
    allowSourceEditing?: boolean;
};

function ToolbarButton({
    onClick,
    active,
    disabled,
    title,
    children,
}: {
    onClick: () => void;
    active?: boolean;
    disabled?: boolean;
    title: string;
    children: React.ReactNode;
}) {
    return (
        <button
            type="button"
            onClick={onClick}
            disabled={disabled}
            title={title}
            className={`rounded p-1 transition-colors ${
                active
                    ? 'bg-zinc-200 text-zinc-900 dark:bg-zinc-700 dark:text-zinc-100'
                    : 'text-zinc-600 hover:bg-zinc-100 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-100'
            } disabled:pointer-events-none disabled:opacity-40`}
        >
            {children}
        </button>
    );
}

export default function HtmlEditor({
    value,
    onChange,
    placeholder,
    allowSourceEditing = false,
}: Props) {
    const [mode, setMode] = useState<'wysiwyg' | 'source'>('wysiwyg');
    const editor = useEditor({
        extensions: [
            StarterKit,
            Underline,
            Link.configure({ openOnClick: false }),
        ],
        content: value,
        onUpdate: ({ editor }) => {
            const html = editor.isEmpty ? '' : editor.getHTML();
            onChange(html);
        },
        editorProps: {
            attributes: {
                class: 'min-h-[120px] px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none',
            },
        },
    });

    // Keep the editor in sync when the value prop changes externally (e.g. form reset).
    useEffect(() => {
        if (!editor) return;
        const current = editor.isEmpty ? '' : editor.getHTML();
        if (current !== value) {
            editor.commands.setContent(value || '', { emitUpdate: false });
        }
    }, [value, editor]);

    function setLink() {
        const prev = editor?.getAttributes('link').href ?? '';
        const href = window.prompt('URL', prev);
        if (href === null) return;
        if (href === '') {
            editor?.chain().focus().unsetLink().run();
        } else {
            editor?.chain().focus().extendMarkRange('link').setLink({ href }).run();
        }
    }

    return (
        <div className="overflow-hidden rounded-md border border-zinc-200 dark:border-zinc-800">
            {/* Toolbar */}
            <div className="flex items-center gap-0.5 border-b border-zinc-200 bg-zinc-50 px-2 py-1.5 dark:border-zinc-800 dark:bg-zinc-900">
                {mode === 'wysiwyg' && (
                    <>
                        <ToolbarButton
                            onClick={() => editor?.chain().focus().toggleBold().run()}
                            active={editor?.isActive('bold')}
                            title="Bold"
                        >
                            <Bold className="size-3.5" />
                        </ToolbarButton>
                        <ToolbarButton
                            onClick={() => editor?.chain().focus().toggleItalic().run()}
                            active={editor?.isActive('italic')}
                            title="Italic"
                        >
                            <Italic className="size-3.5" />
                        </ToolbarButton>
                        <ToolbarButton
                            onClick={() => editor?.chain().focus().toggleUnderline().run()}
                            active={editor?.isActive('underline')}
                            title="Underline"
                        >
                            <UnderlineIcon className="size-3.5" />
                        </ToolbarButton>

                        <div className="mx-1.5 h-4 w-px bg-zinc-200 dark:bg-zinc-700" />

                        <ToolbarButton
                            onClick={() => editor?.chain().focus().toggleBulletList().run()}
                            active={editor?.isActive('bulletList')}
                            title="Bullet list"
                        >
                            <List className="size-3.5" />
                        </ToolbarButton>
                        <ToolbarButton
                            onClick={() => editor?.chain().focus().toggleOrderedList().run()}
                            active={editor?.isActive('orderedList')}
                            title="Ordered list"
                        >
                            <ListOrdered className="size-3.5" />
                        </ToolbarButton>

                        <div className="mx-1.5 h-4 w-px bg-zinc-200 dark:bg-zinc-700" />

                        <ToolbarButton
                            onClick={setLink}
                            active={editor?.isActive('link')}
                            title="Set link"
                        >
                            <Link2 className="size-3.5" />
                        </ToolbarButton>
                        <ToolbarButton
                            onClick={() => editor?.chain().focus().unsetLink().run()}
                            disabled={!editor?.isActive('link')}
                            title="Remove link"
                        >
                            <Link2Off className="size-3.5" />
                        </ToolbarButton>
                    </>
                )}

                {allowSourceEditing && (
                    <>
                        {mode === 'wysiwyg' && (
                            <div className="mx-1.5 h-4 w-px bg-zinc-200 dark:bg-zinc-700" />
                        )}
                        <ToolbarButton
                            onClick={() =>
                                setMode((current) =>
                                    current === 'wysiwyg' ? 'source' : 'wysiwyg',
                                )
                            }
                            active={mode === 'source'}
                            title={
                                mode === 'source'
                                    ? 'Switch to rich text'
                                    : 'Edit HTML source'
                            }
                        >
                            <Code2 className="size-3.5" />
                        </ToolbarButton>
                    </>
                )}
            </div>

            {/* Editor area */}
            <div className="bg-white dark:bg-zinc-950">
                {mode === 'source' ? (
                    <textarea
                        value={value}
                        onChange={(e) => onChange(e.target.value)}
                        placeholder={placeholder}
                        rows={8}
                        className="min-h-[120px] w-full resize-y bg-transparent px-3 py-2 font-mono text-xs text-zinc-900 focus:outline-none dark:text-zinc-100"
                    />
                ) : (
                    <>
                        {!editor?.isEmpty || value ? null : (
                            <p className="pointer-events-none absolute px-3 py-2 text-sm text-zinc-400">
                                {placeholder}
                            </p>
                        )}
                        <EditorContent editor={editor} />
                    </>
                )}
            </div>
        </div>
    );
}
