import {
    Link2,
    List,
    ListOrdered,
    Quote,
    Redo2,
    RemoveFormatting,
    Undo2,
} from 'lucide-react';
import { useEffect, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';

type RichTextEditorProps = {
    id: string;
    value: string;
    onChange: (value: string) => void;
    className?: string;
};

const blockButtons = [
    { label: 'Párrafo', value: 'P' },
    { label: 'Título', value: 'H2' },
    { label: 'Subtítulo', value: 'H3' },
] as const;

function run(command: string, value?: string) {
    window.document.execCommand(command, false, value);
}

export function RichTextEditor({
    id,
    value,
    onChange,
    className,
}: RichTextEditorProps) {
    const editorRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        if (editorRef.current && editorRef.current.innerHTML !== value) {
            editorRef.current.innerHTML = value;
        }
    }, [value]);

    function sync() {
        onChange(editorRef.current?.innerHTML ?? '');
    }

    function withFocus(callback: () => void) {
        editorRef.current?.focus();
        callback();
        sync();
    }

    function insertLink() {
        const url = window.prompt('URL del enlace');

        if (!url?.trim()) {
            return;
        }

        withFocus(() => run('createLink', url.trim()));
    }

    return (
        <div
            className={cn(
                'overflow-hidden rounded-lg border border-input bg-background shadow-xs',
                className,
            )}
        >
            <div className="flex flex-wrap items-center gap-1 border-b border-border bg-muted/30 p-2">
                {blockButtons.map((button) => (
                    <Button
                        key={button.value}
                        size="sm"
                        type="button"
                        variant="ghost"
                        onClick={() =>
                            withFocus(() => run('formatBlock', button.value))
                        }
                    >
                        {button.label}
                    </Button>
                ))}
                <span className="mx-1 h-6 w-px bg-border" aria-hidden />
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('bold'))}
                >
                    <strong>B</strong>
                </Button>
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('italic'))}
                >
                    <em>I</em>
                </Button>
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('underline'))}
                >
                    <span className="underline">U</span>
                </Button>
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(insertLink)}
                >
                    <Link2 className="size-4" />
                    <span className="sr-only">Agregar enlace</span>
                </Button>
                <span className="mx-1 h-6 w-px bg-border" aria-hidden />
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('insertUnorderedList'))}
                >
                    <List className="size-4" />
                    <span className="sr-only">Lista con viñetas</span>
                </Button>
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('insertOrderedList'))}
                >
                    <ListOrdered className="size-4" />
                    <span className="sr-only">Lista numerada</span>
                </Button>
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() =>
                        withFocus(() => run('formatBlock', 'BLOCKQUOTE'))
                    }
                >
                    <Quote className="size-4" />
                    <span className="sr-only">Cita</span>
                </Button>
                <span className="mx-1 h-6 w-px bg-border" aria-hidden />
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('undo'))}
                >
                    <Undo2 className="size-4" />
                    <span className="sr-only">Deshacer</span>
                </Button>
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('redo'))}
                >
                    <Redo2 className="size-4" />
                    <span className="sr-only">Rehacer</span>
                </Button>
                <Button
                    size="sm"
                    type="button"
                    variant="ghost"
                    onClick={() => withFocus(() => run('removeFormat'))}
                >
                    <RemoveFormatting className="size-4" />
                    <span className="sr-only">Quitar formato</span>
                </Button>
            </div>
            <div
                id={id}
                ref={editorRef}
                aria-label="Editor de contenido"
                className="min-h-72 px-4 py-3 text-sm leading-7 outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 [&_a]:text-primary [&_a]:underline [&_blockquote]:border-l-4 [&_blockquote]:pl-4 [&_blockquote]:text-muted-foreground [&_h2]:mt-4 [&_h2]:text-xl [&_h2]:font-semibold [&_h3]:mt-3 [&_h3]:text-lg [&_h3]:font-semibold [&_li]:ml-5 [&_ol]:list-decimal [&_p]:my-2 [&_ul]:list-disc"
                contentEditable
                role="textbox"
                suppressContentEditableWarning
                onInput={sync}
                onBlur={sync}
                onPaste={(event) => {
                    event.preventDefault();
                    const text = event.clipboardData.getData('text/plain');
                    run('insertText', text);
                    sync();
                }}
            />
        </div>
    );
}
