"use client"

// @-tagging (ADR-063) -- delt UI mellom innleggs-komposereren
// (round-messages.tsx) og kommentar-komposereren (post-engagement.tsx).
// Selve logikken (offset-regning, tekst-diffing) er bevisst flyttet ut i
// lib/mentions.ts og enhetstestet der -- denne fila er ren presentasjon
// og DOM-/fokushåndtering.

import type React from "react"
import Link from "next/link"
import { useEffect, useRef, useState } from "react"
import { cn } from "@/lib/utils"
import {
  adjustTagsForEdit,
  detectActiveMention,
  fetchTaggablePeople,
  insertMention,
  segmentTaggedText,
  type Tag,
  type TaggablePerson,
} from "@/lib/mentions"

type MentionTextareaProps = {
  roundId: string
  value: string
  tags: Tag[]
  onChange: (value: string, tags: Tag[]) => void
  placeholder?: string
  rows?: number
  id?: string
  className?: string
  autoFocus?: boolean
  // Videresendes KUN når dropdownen ikke er åpen -- Enter/piltaster skal
  // styre forslagslisten når den vises, ikke utløse f.eks. avsenderens
  // egen Cmd/Ctrl+Enter-innsending samtidig (post-engagement.tsx).
  onKeyDownWhenClosed?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void
}

export function MentionTextarea({
  roundId,
  value,
  tags,
  onChange,
  placeholder,
  rows = 3,
  id,
  className,
  autoFocus,
  onKeyDownWhenClosed,
}: MentionTextareaProps) {
  const textareaRef = useRef<HTMLTextAreaElement | null>(null)
  const [mention, setMention] = useState<{ start: number; query: string } | null>(null)
  const [suggestions, setSuggestions] = useState<TaggablePerson[]>([])
  const [loadingSuggestions, setLoadingSuggestions] = useState(false)
  const [highlighted, setHighlighted] = useState(0)
  // Markørposisjonen som stod da @-forsøket sist ble oppdatert -- trengs
  // for å vite hvor SLUTTEN av "@søketekst" er ved faktisk innsetting
  // (markøren kan ha rukket å flytte seg videre siden selve deteksjonen).
  const cursorAtDetectionRef = useRef(0)
  const pendingCursorRef = useRef<number | null>(null)

  const open = mention !== null

  // Debouncet henting av kandidater -- kun mens dropdownen faktisk er åpen.
  useEffect(() => {
    if (!open) {
      setSuggestions([])
      return
    }
    let cancelled = false
    setLoadingSuggestions(true)
    const handle = setTimeout(async () => {
      const people = await fetchTaggablePeople(roundId, mention.query)
      if (!cancelled) {
        setSuggestions(people)
        setHighlighted(0)
        setLoadingSuggestions(false)
      }
    }, 200)
    return () => {
      cancelled = true
      clearTimeout(handle)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps -- kun query/roundId skal trigge ny henting
  }, [open, mention?.query, roundId])

  // Sett markøren riktig sted ETTER at React har rendret den nye,
  // lengre/kortere verdien -- kan ikke gjøres synkront i onChange, siden
  // <textarea>s DOM-verdi ikke er oppdatert med den nye teksten ennå der.
  useEffect(() => {
    if (pendingCursorRef.current !== null && textareaRef.current) {
      textareaRef.current.setSelectionRange(pendingCursorRef.current, pendingCursorRef.current)
      pendingCursorRef.current = null
    }
  }, [value])

  function handleChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
    const newValue = e.target.value
    const cursor = e.target.selectionStart
    const adjustedTags = adjustTagsForEdit(value, newValue, tags)
    onChange(newValue, adjustedTags)

    const active = detectActiveMention(newValue, cursor)
    cursorAtDetectionRef.current = cursor
    setMention(active)
  }

  function selectSuggestion(person: TaggablePerson) {
    if (!mention || !textareaRef.current) return
    const { body: newBody, tag, cursor } = insertMention(value, mention.start, cursorAtDetectionRef.current, person)
    onChange(newBody, [...tags, tag])
    setMention(null)
    pendingCursorRef.current = cursor
    textareaRef.current.focus()
  }

  function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
    if (open && suggestions.length > 0) {
      if (e.key === "ArrowDown") {
        e.preventDefault()
        setHighlighted((i) => (i + 1) % suggestions.length)
        return
      }
      if (e.key === "ArrowUp") {
        e.preventDefault()
        setHighlighted((i) => (i - 1 + suggestions.length) % suggestions.length)
        return
      }
      if (e.key === "Enter" || e.key === "Tab") {
        e.preventDefault()
        selectSuggestion(suggestions[highlighted])
        return
      }
      if (e.key === "Escape") {
        e.preventDefault()
        setMention(null)
        return
      }
    } else if (open && e.key === "Escape") {
      e.preventDefault()
      setMention(null)
      return
    }
    onKeyDownWhenClosed?.(e)
  }

  return (
    <div className="relative">
      <textarea
        ref={textareaRef}
        id={id}
        autoFocus={autoFocus}
        value={value}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
        onBlur={() => {
          // Liten forsinkelse: en mouseDown på et forslag skal rekke å
          // trigge FØR blur lukker listen (ellers mistes klikket).
          window.setTimeout(() => setMention(null), 150)
        }}
        placeholder={placeholder}
        rows={rows}
        className={className}
      />

      {open && (
        <div
          role="listbox"
          aria-label="Forslag til tagging"
          className="absolute left-0 right-0 top-full z-20 mt-1 max-h-60 overflow-y-auto rounded-xl border border-border bg-card shadow-lg"
        >
          {loadingSuggestions ? (
            <div className="flex items-center justify-center p-3">
              <span
                aria-hidden="true"
                className="size-5 animate-spin rounded-full border-2 border-primary/20 border-t-primary"
              />
              <span className="sr-only">Søker...</span>
            </div>
          ) : suggestions.length === 0 ? (
            <p className="p-3 text-sm text-muted-foreground">Ingen treff</p>
          ) : (
            <ul>
              {suggestions.map((person, i) => (
                <li key={person.user_id}>
                  <button
                    type="button"
                    role="option"
                    aria-selected={i === highlighted}
                    onMouseDown={(e) => {
                      // preventDefault: unngår at textarea mister fokus
                      // FØR onClick rekker å kjøre.
                      e.preventDefault()
                      selectSuggestion(person)
                    }}
                    onMouseEnter={() => setHighlighted(i)}
                    className={cn(
                      "flex min-h-11 w-full items-center px-3 text-left text-base text-foreground",
                      i === highlighted ? "bg-accent" : "hover:bg-accent/50",
                    )}
                  >
                    {person.display_name}
                  </button>
                </li>
              ))}
            </ul>
          )}
        </div>
      )}
    </div>
  )
}

/** Rendrer body-tekst med taggede utsnitt som lenker til vedkommendes
 * profil (`/my-friends/{id}`) -- tydelig annerledes enn vanlig tekst,
 * bevisst UTEN understrek (ligger for tett inntil resten av teksten
 * visuelt sett til at en vanlig lenkestil er lesbar der). */
export function TaggedText({ body, tags, className }: { body: string; tags: Tag[]; className?: string }) {
  if (tags.length === 0) return <span className={className}>{body}</span>
  const segments = segmentTaggedText(body, tags)
  return (
    <span className={className}>
      {segments.map((seg, i) =>
        seg.tag ? (
          <Link
            key={i}
            href={`/my-friends/${seg.tag.user_id}`}
            className="font-semibold text-primary no-underline hover:underline"
          >
            {seg.text}
          </Link>
        ) : (
          <span key={i}>{seg.text}</span>
        ),
      )}
    </span>
  )
}
