"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { CSSProperties, ReactNode } from "react";
import {
  AlignCenter,
  AlignJustify,
  AlignLeft,
  AlignRight,
  Bold,
  Heading1,
  Heading2,
  Italic,
  Link as LinkIcon,
  List,
  ListOrdered,
  Quote,
  Redo2,
  RemoveFormatting,
  Strikethrough,
  SquareCode,
  Type,
  Underline,
  Unlink,
  Undo2,
} from "lucide-react";

type RichTextEditorProps = {
  value: string;
  onChange: (nextValue: string) => void;
  placeholder?: string;
  minHeight?: number;
};

type ToolbarButtonProps = {
  label: string;
  onPress: () => void;
  children: ReactNode;
};

function ToolbarButton({ label, onPress, children }: ToolbarButtonProps) {
  return (
    <button
      type="button"
      onMouseDown={(event) => {
        event.preventDefault();
        onPress();
      }}
      className="inline-flex h-8 w-8 items-center justify-center rounded-md border border-[rgba(198,203,224,0.9)] bg-white text-[var(--ks-color-text-soft)] hover:text-[var(--ks-color-text-primary)] hover:border-[rgba(10,192,214,0.4)] transition-colors"
      aria-label={label}
      title={label}
    >
      {children}
    </button>
  );
}

function safeLinkUrl(raw: string) {
  const value = raw.trim();
  if (!value) return "";
  if (/^(https?:\/\/|mailto:|tel:)/i.test(value)) return value;
  return `https://${value}`;
}

function stripHtml(value: string) {
  return value.replace(/<[^>]*>/g, " ").replace(/&nbsp;/g, " ");
}

export function RichTextEditor({
  value,
  onChange,
  placeholder = "Digite a descricao...",
  minHeight = 180,
}: RichTextEditorProps) {
  const editorRef = useRef<HTMLDivElement>(null);
  const [textColor, setTextColor] = useState("#111827");
  const [highlightColor, setHighlightColor] = useState("#fff8cc");
  const isEmpty = useMemo(() => stripHtml(value).trim().length === 0, [value]);

  const emitChange = useCallback(() => {
    const html = editorRef.current?.innerHTML ?? "";
    onChange(html);
  }, [onChange]);

  const runCommand = useCallback(
    (command: string, commandValue?: string) => {
      if (!editorRef.current) return;
      editorRef.current.focus();
      document.execCommand(command, false, commandValue);
      emitChange();
    },
    [emitChange]
  );

  const applyBlock = useCallback(
    (tag: "p" | "h1" | "h2" | "blockquote" | "pre") => {
      runCommand("formatBlock", `<${tag}>`);
    },
    [runCommand]
  );

  /*
    Caixa de link propria, e nao a do navegador.

    O prompt do navegador some com a selecao do texto em alguns navegadores e
    mostra "localhost diz" no meio da tela. Aqui a selecao fica guardada ate a
    pessoa confirmar.
  */
  const [linkAberto, setLinkAberto] = useState(false);
  const [linkDigitado, setLinkDigitado] = useState("https://");
  const selecaoDoLink = useRef<Range | null>(null);

  const setSelectionLink = useCallback(() => {
    const selecao = window.getSelection();
    const texto = selecao?.toString().trim() || "";
    selecaoDoLink.current = selecao && selecao.rangeCount > 0 ? selecao.getRangeAt(0).cloneRange() : null;
    setLinkDigitado(texto.startsWith("http") ? texto : "https://");
    setLinkAberto(true);
  }, []);

  const confirmarLink = useCallback(() => {
    const href = safeLinkUrl(linkDigitado);
    setLinkAberto(false);
    if (!href) return;

    /* Devolve a selecao antes de aplicar: o clique no campo tirou o foco do
       texto que a pessoa queria transformar em link. */
    const selecao = window.getSelection();
    if (selecaoDoLink.current && selecao) {
      selecao.removeAllRanges();
      selecao.addRange(selecaoDoLink.current);
    }
    runCommand("createLink", href);
  }, [linkDigitado, runCommand]);

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

  const editorStyle = useMemo(
    () =>
      ({
        minHeight: `${Math.max(minHeight, 120)}px`,
      }) satisfies CSSProperties,
    [minHeight]
  );

  return (
    <div className="rounded-2xl border border-[rgba(198,203,224,0.9)] bg-white overflow-hidden">
      <div className="flex flex-wrap items-center gap-2 border-b border-[rgba(198,203,224,0.6)] bg-[var(--ks-color-bg-soft)] p-2">
        <ToolbarButton label="Desfazer" onPress={() => runCommand("undo")}>
          <Undo2 size={14} />
        </ToolbarButton>
        <ToolbarButton label="Refazer" onPress={() => runCommand("redo")}>
          <Redo2 size={14} />
        </ToolbarButton>

        <div className="h-6 w-px bg-[rgba(198,203,224,0.8)]" />

        <ToolbarButton label="Negrito" onPress={() => runCommand("bold")}>
          <Bold size={14} />
        </ToolbarButton>
        <ToolbarButton label="Italico" onPress={() => runCommand("italic")}>
          <Italic size={14} />
        </ToolbarButton>
        <ToolbarButton label="Sublinhado" onPress={() => runCommand("underline")}>
          <Underline size={14} />
        </ToolbarButton>
        <ToolbarButton label="Riscado" onPress={() => runCommand("strikeThrough")}>
          <Strikethrough size={14} />
        </ToolbarButton>

        <div className="h-6 w-px bg-[rgba(198,203,224,0.8)]" />

        <ToolbarButton label="Paragrafo" onPress={() => applyBlock("p")}>
          <Type size={14} />
        </ToolbarButton>
        <ToolbarButton label="Titulo 1" onPress={() => applyBlock("h1")}>
          <Heading1 size={14} />
        </ToolbarButton>
        <ToolbarButton label="Titulo 2" onPress={() => applyBlock("h2")}>
          <Heading2 size={14} />
        </ToolbarButton>
        <ToolbarButton label="Citacao" onPress={() => applyBlock("blockquote")}>
          <Quote size={14} />
        </ToolbarButton>
        <ToolbarButton label="Codigo" onPress={() => applyBlock("pre")}>
          <SquareCode size={14} />
        </ToolbarButton>

        <div className="h-6 w-px bg-[rgba(198,203,224,0.8)]" />

        <ToolbarButton label="Lista" onPress={() => runCommand("insertUnorderedList")}>
          <List size={14} />
        </ToolbarButton>
        <ToolbarButton label="Lista numerada" onPress={() => runCommand("insertOrderedList")}>
          <ListOrdered size={14} />
        </ToolbarButton>

        <div className="h-6 w-px bg-[rgba(198,203,224,0.8)]" />

        <ToolbarButton label="Alinhar a esquerda" onPress={() => runCommand("justifyLeft")}>
          <AlignLeft size={14} />
        </ToolbarButton>
        <ToolbarButton label="Centralizar" onPress={() => runCommand("justifyCenter")}>
          <AlignCenter size={14} />
        </ToolbarButton>
        <ToolbarButton label="Alinhar a direita" onPress={() => runCommand("justifyRight")}>
          <AlignRight size={14} />
        </ToolbarButton>
        <ToolbarButton label="Justificar" onPress={() => runCommand("justifyFull")}>
          <AlignJustify size={14} />
        </ToolbarButton>

        <div className="h-6 w-px bg-[rgba(198,203,224,0.8)]" />

        <ToolbarButton label="Inserir link" onPress={setSelectionLink}>
          <LinkIcon size={14} />
        </ToolbarButton>
        <ToolbarButton label="Remover link" onPress={() => runCommand("unlink")}>
          <Unlink size={14} />
        </ToolbarButton>

        <div className="h-6 w-px bg-[rgba(198,203,224,0.8)]" />

        <label
          className="inline-flex h-8 items-center gap-1 rounded-md border border-[rgba(198,203,224,0.9)] bg-white px-2 text-xs text-[var(--ks-color-text-soft)]"
          title="Cor do texto"
        >
          A
          <input
            type="color"
            value={textColor}
            onChange={(event) => {
              const nextColor = event.target.value;
              setTextColor(nextColor);
              runCommand("foreColor", nextColor);
            }}
            className="h-4 w-4 cursor-pointer border-0 bg-transparent p-0"
          />
        </label>
        <label
          className="inline-flex h-8 items-center gap-1 rounded-md border border-[rgba(198,203,224,0.9)] bg-white px-2 text-xs text-[var(--ks-color-text-soft)]"
          title="Cor de destaque"
        >
          Bg
          <input
            type="color"
            value={highlightColor}
            onChange={(event) => {
              const nextColor = event.target.value;
              setHighlightColor(nextColor);
              runCommand("hiliteColor", nextColor);
            }}
            className="h-4 w-4 cursor-pointer border-0 bg-transparent p-0"
          />
        </label>

        <ToolbarButton label="Limpar formatacao" onPress={() => runCommand("removeFormat")}>
          <RemoveFormatting size={14} />
        </ToolbarButton>
      </div>

      <div className="relative">
        <div
          ref={editorRef}
          contentEditable
          onInput={emitChange}
          onBlur={emitChange}
          className="prose prose-sm max-w-none px-4 py-3 text-sm text-[var(--ks-color-text-primary)] focus:outline-none"
          style={editorStyle}
          suppressContentEditableWarning
        />
        {isEmpty && (
          <span className="pointer-events-none absolute left-4 top-3 text-sm text-[var(--ks-color-text-soft)]">
            {placeholder}
          </span>
        )}
      </div>

      {linkAberto ? (
        <div
          role="dialog"
          aria-modal="true"
          onClick={() => setLinkAberto(false)}
          className="fixed inset-0 z-[110] flex items-center justify-center bg-[rgba(12,8,24,0.42)] p-6 backdrop-blur-[2px]"
        >
          <div
            onClick={(event) => event.stopPropagation()}
            className="w-[min(420px,100%)] rounded-[18px] bg-white p-5 shadow-[0_24px_60px_rgba(26,26,43,0.28)]"
          >
            <div className="text-[16px] font-extrabold text-[var(--ks-color-text-primary)]">Inserir link</div>
            <p className="mt-1.5 text-[13px] leading-5 text-[var(--ks-color-text-soft)]">
              Cole o endereço completo. O texto que você selecionou vira o link.
            </p>
            <input
              autoFocus
              value={linkDigitado}
              onChange={(event) => setLinkDigitado(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === "Enter") {
                  event.preventDefault();
                  confirmarLink();
                }
                if (event.key === "Escape") setLinkAberto(false);
              }}
              placeholder="https://"
              className="ks-input mt-3 w-full"
            />
            <div className="mt-4 flex justify-end gap-2">
              <button
                type="button"
                onClick={() => setLinkAberto(false)}
                className="h-9 rounded-xl bg-[#f1f0f7] px-4 text-[13px] font-bold text-[var(--ks-color-text-soft)] transition hover:bg-[#e6e6f2]"
              >
                Cancelar
              </button>
              <button
                type="button"
                onClick={confirmarLink}
                className="h-9 rounded-xl bg-[var(--ks-color-primary)] px-4 text-[13px] font-bold text-white transition hover:opacity-90"
              >
                Inserir link
              </button>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  );
}
