"use client"

import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useEditor, EditorContent } from "@tiptap/react"
import type { Editor } from "@tiptap/react"
import StarterKit from "@tiptap/starter-kit"
import Placeholder from "@tiptap/extension-placeholder"
import Mention from "@tiptap/extension-mention"
import { ReactRenderer } from "@tiptap/react"
import tippy, { type Instance, type Props as TippyProps } from "tippy.js"
import { Braces, Trash2 } from "lucide-react"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectEmptyState, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"

// Tipos
type EmailCtaTarget = "AUTO" | "PORTAL" | "STAFF"

type SendEmailAction = {
  id: string
  type: "SEND_EMAIL"
  subject: string
  message: string
  toRequester: boolean
  toAssignee: boolean
  toUserId: string
  toEmails: string
  ctaTarget: EmailCtaTarget
  ctaLabel: string
}

type Agent = {
  _id: string
  name: string
}

type EmailActionConfigProps = {
  action: SendEmailAction
  onChange: (action: SendEmailAction) => void
  onRemove: () => void
  agents: Agent[]
}

// Variáveis disponíveis para interpolação
const EMAIL_VARIABLES = [
  { key: "ticket.reference", label: "Referência", description: "Número do chamado (ex: #1234)" },
  { key: "ticket.subject", label: "Assunto", description: "Título do chamado" },
  { key: "ticket.status", label: "Status", description: "Status atual do chamado" },
  { key: "ticket.priority", label: "Prioridade", description: "Nível de prioridade" },
  { key: "company.name", label: "Empresa", description: "Nome da empresa do solicitante" },
  { key: "requester.name", label: "Solicitante", description: "Nome de quem abriu o chamado" },
  { key: "assignee.name", label: "Responsável", description: "Nome do agente responsável" },
] as const

type EmailVariable = (typeof EMAIL_VARIABLES)[number]

const CLEAR_SELECT_VALUE = "__clear__"

// Estilos do badge de variável (fundo preto com texto branco)
const VARIABLE_BADGE_CLASSES =
  "inline-flex items-center gap-1 rounded-md bg-neutral-900 border border-neutral-700 px-1.5 py-0.5 text-xs font-mono text-white whitespace-nowrap"

// Extensao TipTap para variaveis de e-mail
const EmailVariableMentionExtension = Mention.extend({
  name: "emailVariable",
  priority: 1000,
  group: "inline",
  inline: true,
  selectable: true,
  atom: true,

  addAttributes() {
    return {
      id: { default: null },
      label: { default: null },
    }
  },

  addKeyboardShortcuts() {
    return {
      Backspace: ({ editor }: { editor: Editor }) => {
        const { state } = editor
        const { selection } = state
        if (selection.empty) {
          const { $from } = selection
          const nodeBefore = $from.nodeBefore
          if (nodeBefore?.type?.name === this.name) {
            const from = $from.pos - nodeBefore.nodeSize
            const to = $from.pos
            editor.chain().focus().deleteRange({ from, to }).run()
            return true
          }
        }
        return false
      },
    }
  },

  parseHTML() {
    return [
      {
        tag: `span[data-email-variable]`,
        getAttrs: (dom: HTMLElement | string) => {
          if (dom instanceof HTMLElement) {
            return {
              id: dom.dataset.variableId ?? null,
              label: dom.dataset.variableLabel ?? dom.textContent ?? null,
            }
          }
          return {}
        },
      },
    ]
  },

  renderHTML({ HTMLAttributes }: { HTMLAttributes: Record<string, unknown> }) {
    const id = String(HTMLAttributes.id ?? "")
    const label = String(HTMLAttributes.label ?? id)
    return [
      "span",
      {
        "data-email-variable": "true",
        "data-variable-id": id,
        "data-variable-label": label,
        class: VARIABLE_BADGE_CLASSES,
        contenteditable: "false",
      },
      `{{${id}}}`,
    ]
  },

  addNodeView() {
    return ({ node }) => {
      const dom = document.createElement("span")
      dom.className = VARIABLE_BADGE_CLASSES
      dom.contentEditable = "false"
      dom.dataset.emailVariable = "true"
      dom.dataset.variableId = String(node.attrs.id ?? "")
      dom.dataset.variableLabel = String(node.attrs.label ?? "")
      dom.textContent = `{{${node.attrs.id}}}`
      return { dom }
    }
  },
}).configure({
  suggestion: {
    char: "{{",
    allowSpaces: false,
    startOfLine: false,
    render: () => {
      let component: ReactRenderer | null = null
      let popup: Instance<TippyProps> | null = null
      let keydownHandler: ((event: KeyboardEvent) => boolean) | null = null

      const registerHandler = (handler: ((event: KeyboardEvent) => boolean) | null) => {
        keydownHandler = handler
      }

      return {
        onStart: (props) => {
          component = new ReactRenderer(EmailVariableList, {
            props: { ...props, onRegister: registerHandler },
            editor: props.editor,
          })

          if (!props.clientRect) return

          popup = tippy(document.body, {
            getReferenceClientRect: () => props.clientRect?.() ?? new DOMRect(),
            appendTo: () => document.body,
            content: component.element,
            showOnCreate: true,
            interactive: true,
            trigger: "manual",
            placement: "bottom-start",
            zIndex: 99999,
          })
        },
        onUpdate(props) {
          component?.updateProps({ ...props, onRegister: registerHandler })
          if (!props.clientRect) return
          popup?.setProps({
            getReferenceClientRect: () => props.clientRect?.() ?? new DOMRect(),
          })
        },
        onKeyDown(props) {
          if (props.event.key === "Escape") {
            popup?.hide()
            return true
          }
          if (keydownHandler?.(props.event)) {
            return true
          }
          return false
        },
        onExit() {
          popup?.destroy()
          component?.destroy()
          keydownHandler = null
        },
      }
    },
    items: ({ query }) => {
      const q = query.toLowerCase().replace(/^\{*/, "")
      return EMAIL_VARIABLES.filter(
        (v) =>
          v.key.toLowerCase().includes(q) ||
          v.label.toLowerCase().includes(q) ||
          v.description.toLowerCase().includes(q)
      )
    },
  },
})

// Lista de sugestoes de variaveis
type EmailVariableListProps = {
  items: EmailVariable[]
  command: (item: { id: string; label: string }) => void
  onRegister?: (handler: ((event: KeyboardEvent) => boolean) | null) => void
}

function EmailVariableList({ items, command, onRegister }: EmailVariableListProps) {
  const [selectedIndex, setSelectedIndex] = useState(0)

  const selectItem = useCallback(
    (index: number) => {
      const item = items[index]
      if (item) {
        command({ id: item.key, label: item.label })
      }
    },
    [command, items]
  )

  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      if (event.key === "ArrowUp") {
        setSelectedIndex((prev) => (prev + items.length - 1) % items.length)
        return true
      }
      if (event.key === "ArrowDown") {
        setSelectedIndex((prev) => (prev + 1) % items.length)
        return true
      }
      if (event.key === "Enter") {
        selectItem(selectedIndex)
        return true
      }
      return false
    },
    [items.length, selectItem, selectedIndex]
  )

  useEffect(() => {
    onRegister?.(handleKeyDown)
    return () => onRegister?.(null)
  }, [handleKeyDown, onRegister])

  useEffect(() => {
    setSelectedIndex(0)
  }, [items])

  if (!items.length) {
    return (
      <div className="rounded-lg border bg-white p-3 text-sm text-muted-foreground shadow-lg">
        Nenhuma variavel encontrada
      </div>
    )
  }

  return (
    <div className="max-h-64 min-w-[280px] overflow-y-auto rounded-lg border bg-white p-1 shadow-lg">
      {items.map((item, index) => (
        <button
          key={item.key}
          type="button"
          className={cn(
            "flex w-full flex-col gap-0.5 rounded-md px-3 py-2 text-left transition",
            index === selectedIndex ? "bg-neutral-100" : "hover:bg-slate-50"
          )}
          onMouseEnter={() => setSelectedIndex(index)}
          onMouseDown={(e) => {
            e.preventDefault()
            selectItem(index)
          }}
        >
          <span className="font-mono text-sm text-neutral-900">{`{{${item.key}}}`}</span>
          <span className="text-xs text-muted-foreground">{item.description}</span>
        </button>
      ))}
    </div>
  )
}

// Converte HTML com badges para texto com {{variaveis}}
function htmlToPlainVariables(html: string): string {
  if (!html) return ""
  // Remove tags HTML mantendo o texto
  const div = document.createElement("div")
  div.innerHTML = html
  // Badges de variavel ja tem o texto {{variavel}} dentro
  return div.textContent ?? ""
}

// Converte texto com {{variaveis}} para HTML com badges
function plainVariablesToHtml(text: string): string {
  if (!text) return ""
  // Escapa HTML primeiro
  const escaped = text
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
  // Converte {{var}} para badges
  return escaped.replace(/\{\{([^}]+)\}\}/g, (_, varKey) => {
    const variable = EMAIL_VARIABLES.find((v) => v.key === varKey)
    const label = variable?.label ?? varKey
    return `<span data-email-variable="true" data-variable-id="${varKey}" data-variable-label="${label}" class="${VARIABLE_BADGE_CLASSES}">{{${varKey}}}</span>`
  })
}

// Editor de mensagem com suporte a variaveis
type MessageEditorProps = {
  value: string
  onChange: (value: string) => void
  onInsertVariable: (ref: { insertVariable: (key: string) => void } | null) => void
}

function MessageEditor({ value, onChange, onInsertVariable }: MessageEditorProps) {
  // eslint-disable-next-line react-hooks/exhaustive-deps -- initialContent deve ser calculado apenas uma vez na montagem
  const initialContent = useMemo(() => plainVariablesToHtml(value), [])

  const editor = useEditor({
    extensions: [
      StarterKit.configure({
        bulletList: false,
        orderedList: false,
        blockquote: false,
        codeBlock: false,
        heading: false,
        horizontalRule: false,
      }),
      Placeholder.configure({ placeholder: "Escreva a mensagem do e-mail..." }),
      EmailVariableMentionExtension,
    ],
    content: initialContent,
    editorProps: {
      attributes: {
        class: "prose prose-sm max-w-none focus:outline-none min-h-[100px] p-3 text-sm",
      },
    },
    onUpdate({ editor }) {
      const html = editor.getHTML()
      const plain = htmlToPlainVariables(html)
      onChange(plain)
    },
    immediatelyRender: false,
  })

  // Expoe metodo para inserir variavel externamente
  useEffect(() => {
    if (!editor) {
      onInsertVariable(null)
      return
    }

    onInsertVariable({
      insertVariable: (key: string) => {
        const variable = EMAIL_VARIABLES.find((v) => v.key === key)
        if (!variable) return
        editor
          .chain()
          .focus()
          .insertContent({
            type: "emailVariable",
            attrs: { id: key, label: variable.label },
          })
          .run()
      },
    })

    return () => onInsertVariable(null)
  }, [editor, onInsertVariable])

  // Sincroniza valor externo
  useEffect(() => {
    if (!editor) return
    const currentPlain = htmlToPlainVariables(editor.getHTML())
    if (currentPlain !== value) {
      editor.commands.setContent(plainVariablesToHtml(value), { emitUpdate: false })
    }
  }, [value, editor])

  if (!editor) return null

  return (
    <div className="rounded-lg border bg-white focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2">
      <EditorContent editor={editor} />
    </div>
  )
}

// Componente principal
export function EmailActionConfig({ action, onChange, onRemove, agents }: EmailActionConfigProps) {
  const subjectInputRef = useRef<HTMLInputElement>(null)
  const messageEditorRef = useRef<{ insertVariable: (key: string) => void } | null>(null)
  const [activeField, setActiveField] = useState<"subject" | "message">("message")

  const handleChange = useCallback(
    <K extends keyof SendEmailAction>(key: K, value: SendEmailAction[K]) => {
      onChange({ ...action, [key]: value })
    },
    [action, onChange]
  )

  const handleInsertVariable = useCallback(
    (variable: EmailVariable) => {
      if (activeField === "subject" && subjectInputRef.current) {
        const input = subjectInputRef.current
        const start = input.selectionStart ?? input.value.length
        const end = input.selectionEnd ?? input.value.length
        const varText = `{{${variable.key}}}`
        const newValue = input.value.slice(0, start) + varText + input.value.slice(end)
        handleChange("subject", newValue)
        // Reposiciona cursor apos a variavel
        requestAnimationFrame(() => {
          input.focus()
          const newPos = start + varText.length
          input.setSelectionRange(newPos, newPos)
        })
      } else if (activeField === "message" && messageEditorRef.current) {
        messageEditorRef.current.insertVariable(variable.key)
      }
    },
    [activeField, handleChange]
  )

  return (
    <div className="space-y-4">
      {/* Header com tipo e botão de remover */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <div className="flex size-8 items-center justify-center rounded-lg bg-neutral-900">
            <Braces className="size-4 text-white" />
          </div>
          <span className="font-medium text-neutral-900">Enviar e-mail</span>
        </div>
        <Button
          type="button"
          variant="ghost"
          size="icon"
          onClick={onRemove}
          className="h-8 w-8 text-slate-500 hover:bg-red-50 hover:text-red-700"
          title="Remover ação"
        >
          <Trash2 className="size-4" />
        </Button>
      </div>

      {/* Assunto */}
      <div className="space-y-1.5">
        <Label className="text-sm font-medium">Assunto do e-mail</Label>
        <Input
          ref={subjectInputRef}
          value={action.subject}
          onChange={(e) => handleChange("subject", e.target.value)}
          onFocus={() => setActiveField("subject")}
          placeholder="Ex.: Atualizacao do chamado #{{ticket.reference}}"
        />
      </div>

      {/* Mensagem */}
      <div className="space-y-1.5">
        <Label className="text-sm font-medium">Mensagem</Label>
        <div onFocus={() => setActiveField("message")}>
          <MessageEditor
            value={action.message}
            onChange={(v) => handleChange("message", v)}
            onInsertVariable={(ref) => {
              messageEditorRef.current = ref
            }}
          />
        </div>
      </div>

      {/* Paleta de variáveis */}
      <div className="space-y-2">
        <Label className="text-xs text-muted-foreground">
          Variáveis disponíveis (arraste ou clique para inserir no {activeField === "subject" ? "assunto" : "corpo"})
        </Label>
        <div className="flex flex-wrap gap-1.5">
          {EMAIL_VARIABLES.map((variable) => (
            <Tooltip key={variable.key}>
              <TooltipTrigger asChild>
                <button
                  type="button"
                  draggable
                  onClick={() => handleInsertVariable(variable)}
                  onDragStart={(e) => {
                    e.dataTransfer.setData("text/plain", `{{${variable.key}}}`)
                    e.dataTransfer.effectAllowed = "copy"
                  }}
                  className={cn(
                    VARIABLE_BADGE_CLASSES,
                    "cursor-grab transition hover:bg-neutral-800 active:cursor-grabbing"
                  )}
                >
                  {`{{${variable.key}}}`}
                </button>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="text-xs">
                {variable.description}
              </TooltipContent>
            </Tooltip>
          ))}
        </div>
      </div>

      {/* Destinatários */}
      <div className="space-y-3 rounded-lg border border-slate-200 bg-slate-50/50 p-4">
        <Label className="text-sm font-medium">Destinatários</Label>

        <div className="flex flex-wrap gap-4">
          <label className="flex items-center gap-2 text-sm text-neutral-700">
            <Checkbox
              checked={action.toRequester}
              onCheckedChange={(checked) => handleChange("toRequester", Boolean(checked))}
            />
            Solicitante do ticket
          </label>
          <label className="flex items-center gap-2 text-sm text-neutral-700">
            <Checkbox
              checked={action.toAssignee}
              onCheckedChange={(checked) => handleChange("toAssignee", Boolean(checked))}
            />
            Responsável do ticket
          </label>
        </div>

        <div className="grid gap-3 sm:grid-cols-2">
          <div className="space-y-1.5">
            <Label className="text-xs text-muted-foreground">Agente específico (opcional)</Label>
            <Select
              value={action.toUserId}
              onValueChange={(value) => {
                const nextValue = value === CLEAR_SELECT_VALUE ? "" : value
                handleChange("toUserId", nextValue)
              }}
            >
              <SelectTrigger className="bg-white">
                <SelectValue placeholder="Selecione" />
              </SelectTrigger>
              <SelectContent className="rounded-xl">
                {agents.length === 0 ? (
                  <SelectEmptyState
                    message="Nenhum agente disponível"
                    createLabel="Gerenciar usuários"
                    createHref="/admin/users"
                  />
                ) : (
                  <>
                    <SelectItem value={CLEAR_SELECT_VALUE}>Nenhum</SelectItem>
                    {agents.map((u) => (
                      <SelectItem key={u._id} value={String(u._id)}>
                        {u.name}
                      </SelectItem>
                    ))}
                  </>
                )}
              </SelectContent>
            </Select>
          </div>

          <div className="space-y-1.5">
            <Label className="text-xs text-muted-foreground">E-mails adicionais</Label>
            <Input
              value={action.toEmails}
              onChange={(e) => handleChange("toEmails", e.target.value)}
              placeholder="cliente@empresa.com, outro@dominio.com"
              className="bg-white"
            />
          </div>
        </div>
      </div>

      {/* Botão do e-mail */}
      <div className="grid gap-3 sm:grid-cols-2">
        <div className="space-y-1.5">
          <Label className="text-xs text-muted-foreground">Link do botão</Label>
          <Select
            value={action.ctaTarget}
            onValueChange={(value) => handleChange("ctaTarget", value as EmailCtaTarget)}
          >
            <SelectTrigger>
              <SelectValue />
            </SelectTrigger>
            <SelectContent className="rounded-xl">
              <SelectItem value="AUTO">Auto (detecta pelo destinatario)</SelectItem>
              <SelectItem value="PORTAL">Portal (cliente)</SelectItem>
              <SelectItem value="STAFF">Painel (agente)</SelectItem>
            </SelectContent>
          </Select>
        </div>

        <div className="space-y-1.5">
          <Label className="text-xs text-muted-foreground">Texto do botão</Label>
          <Input
            value={action.ctaLabel}
            onChange={(e) => handleChange("ctaLabel", e.target.value)}
            placeholder="Abrir chamado"
          />
        </div>
      </div>
    </div>
  )
}
