'use client'

import { useState, useTransition, useEffect, useRef } from 'react'
import type { Note } from '@/lib/types'
import { getNoteFeedImage, getNotePlainExcerpt, getNoteDisplayTitle } from '@/lib/note-preview'
import { useLanguage } from '@/lib/i18n'
import { emitNoteChange, type NoteCollectionActions } from '@/lib/note-change-sync'
import { motion, AnimatePresence } from 'motion/react'
import { ChevronRight, MoreHorizontal, Trash2, Archive, Pin, History, Pencil, Sparkles, Loader2, Bell, FolderOpen, FileText } from 'lucide-react'
import { useLabelsQuery } from '@/lib/query-hooks'
import { useSession } from 'next-auth/react'
import { getAISettings } from '@/app/actions/ai-settings'
import { generateNoteIllustrationSvg } from '@/app/actions/note-illustration'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { MoveToNotebookPickerPortal } from '@/components/move-to-notebook-picker'
import { deleteNote, toggleArchive, togglePin, updateNote } from '@/app/actions/notes'
import { ReminderDialog } from '@/components/reminder-dialog'
import { useNotebooks } from '@/context/notebooks-context'
import { toast } from 'sonner'
import { ConfirmDeleteNoteDialog } from '@/components/confirm-delete-note-dialog'
import { showNoteTrashedToast } from '@/lib/notes/trash-toast'
import { NoteSelectCheckbox } from '@/components/note-select-checkbox'
import { dateTextDirection, formatNoteCalendarDate } from '@/lib/utils/format-localized-date'
import { sanitizeIllustrationSvg } from '@/lib/sanitize-content'
import { cn } from '@/lib/utils'
import { useHydrated } from '@/lib/use-hydrated'

type NotesEditorialViewProps = {
  notes: Note[]
  onOpen: (note: Note, readOnly?: boolean) => void
  notebookName?: string
  onOpenHistory?: (note: Note) => void
  selection?: {
    selectedIds: ReadonlySet<string>
    onToggle: (id: string) => void
  }
} & NoteCollectionActions

function formatNoteDate(date: Date | string, language: string): string {
  return formatNoteCalendarDate(date, language)
}

export function EditorialNoteMenu({
  note,
  onOpen,
  onOpenHistory,
  onTogglePin,
  onDeleteNote,
  onArchiveNote,
  onMoveToNotebook,
  onNotePatch,
}: {
  note: Note
  onOpen: (note: Note) => void
  onOpenHistory?: (note: Note) => void
} & NoteCollectionActions) {
  const { t } = useLanguage()
  const { notebooks } = useNotebooks()
  const [, startTransition] = useTransition()
  const [showReminder, setShowReminder] = useState(false)
  const [movePickerOpen, setMovePickerOpen] = useState(false)
  const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false)
  const menuTriggerRef = useRef<HTMLButtonElement>(null)

  const handleDelete = (e: React.MouseEvent) => {
    e.stopPropagation()
    if (onDeleteNote) {
      onDeleteNote(note)
      return
    }
    setConfirmDeleteOpen(true)
  }

  const confirmFallbackDelete = () => {
    startTransition(async () => {
      try {
        await deleteNote(note.id, { skipRevalidation: true })
        emitNoteChange({ type: 'deleted', noteId: note.id, notebookId: note.notebookId })
        showNoteTrashedToast(note, t)
      } catch {
        toast.error(t('general.error'))
      }
    })
  }

  const handleArchive = (e: React.MouseEvent) => {
    e.stopPropagation()
    if (onArchiveNote) {
      onArchiveNote(note)
      return
    }
    startTransition(async () => {
      try {
        await toggleArchive(note.id, !note.isArchived, { skipRevalidation: true })
        emitNoteChange({ type: 'updated', note: { ...note, isArchived: !note.isArchived } })
        toast.success(note.isArchived ? (t('notes.unarchived') || 'Désarchivée') : (t('notes.archived') || 'Archivée'))
      } catch {
        toast.error(t('general.error'))
      }
    })
  }

  const handlePin = (e: React.MouseEvent) => {
    e.stopPropagation()
    if (onTogglePin) {
      onTogglePin(note)
      return
    }
    startTransition(async () => {
      try {
        const nextPinned = !note.isPinned
        await togglePin(note.id, nextPinned, { skipRevalidation: true })
        emitNoteChange({ type: 'updated', note: { ...note, isPinned: nextPinned } })
      } catch {
        toast.error(t('general.error'))
      }
    })
  }

  const handleMoveToNotebook = (notebookId: string | null) => {
    if (onMoveToNotebook) {
      onMoveToNotebook(note, notebookId)
      return
    }
    startTransition(async () => {
      try {
        await updateNote(note.id, { notebookId }, { skipRevalidation: true })
        emitNoteChange({ type: 'updated', note: { ...note, notebookId } })
        toast.success(t('notebookSuggestion.movedToNotebook') || 'Note déplacée')
      } catch {
        toast.error(t('general.error'))
      }
    })
  }

  const patchReminder = (reminder: Date | null) => {
    startTransition(async () => {
      try {
        await updateNote(note.id, { reminder }, { skipRevalidation: true })
        const patch = { reminder: (reminder?.toISOString() ?? null) as any }
        onNotePatch?.(note.id, patch)
        emitNoteChange({ type: 'updated', note: { ...note, reminder: patch.reminder } as any })
        setShowReminder(false)
      } catch {
        toast.error(t('general.error'))
      }
    })
  }

  return (
    <>
      <DropdownMenu>
        <DropdownMenuTrigger asChild onClick={e => e.stopPropagation()}>
          <button
            ref={menuTriggerRef}
            className="opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity p-1.5 rounded-md hover:bg-muted/60 text-muted-foreground hover:text-foreground cursor-pointer"
            aria-label={t('notes.moreOptions') || 'Options'}
          >
            <MoreHorizontal size={15} />
          </button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end" className="w-52">
          <DropdownMenuItem onClick={e => { e.stopPropagation(); onOpen(note) }}>
            <Pencil className="h-4 w-4 me-2 text-foreground/50" />
            {t('notes.open') || 'Ouvrir'}
          </DropdownMenuItem>
          <DropdownMenuItem onClick={handlePin}>
            <Pin className="h-4 w-4 me-2 text-foreground/50" />
            {note.isPinned ? (t('notes.unpin') || 'Désépingler') : (t('notes.pin') || 'Épingler')}
          </DropdownMenuItem>
          <DropdownMenuItem onClick={handleArchive}>
            <Archive className="h-4 w-4 me-2 text-foreground/50" />
            {note.isArchived ? (t('notes.unarchive') || 'Désarchiver') : (t('notes.archive') || 'Archiver')}
          </DropdownMenuItem>
          {onOpenHistory && (
            <DropdownMenuItem onClick={e => { e.stopPropagation(); onOpenHistory(note) }}>
              <History className="h-4 w-4 me-2 text-foreground/50" />
              {t('notes.history') || 'Historique'}
            </DropdownMenuItem>
          )}

          {/* Rappel */}
          <DropdownMenuItem onClick={e => { e.stopPropagation(); setShowReminder(true) }}>
            <Bell className="h-4 w-4 me-2 text-foreground/50" />
            {note.reminder
              ? (t('reminder.changeReminder') || 'Modifier le rappel')
              : (t('reminder.setReminder') || 'Définir un rappel')}
          </DropdownMenuItem>

          {/* Déplacer vers un carnet */}
          <DropdownMenuItem
            onClick={e => {
              e.stopPropagation()
              setMovePickerOpen(true)
            }}
          >
            <FolderOpen className="h-4 w-4 me-2 text-foreground/50" />
            {t('notebookSuggestion.moveToNotebook') || 'Déplacer vers…'}
          </DropdownMenuItem>

          <DropdownMenuSeparator />
          <DropdownMenuItem onClick={handleDelete} className="text-destructive focus:text-destructive focus:bg-destructive/10">
            <Trash2 className="h-4 w-4 me-2" />
            {t('notes.delete') || 'Supprimer'}
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>

      <MoveToNotebookPickerPortal
        open={movePickerOpen}
        onOpenChange={setMovePickerOpen}
        anchorRef={menuTriggerRef}
        notebooks={notebooks}
        currentNotebookId={note.notebookId}
        onSelect={handleMoveToNotebook}
        align="end"
        preferDropUp
      />

      {/* ReminderDialog hors du DropdownMenu pour éviter les conflits de portail */}
      <ReminderDialog
        open={showReminder}
        onOpenChange={setShowReminder}
        currentReminder={note.reminder ? new Date(note.reminder) : null}
        onSave={(date) => patchReminder(date)}
        onRemove={() => patchReminder(null)}
      />

      <ConfirmDeleteNoteDialog
        open={confirmDeleteOpen}
        onOpenChange={setConfirmDeleteOpen}
        onConfirm={confirmFallbackDelete}
      />
    </>
  )
}

function EditorialThumbnail({
  note,
  title,
  aiIllustrationEnabled,
  onNoteIllustrationGenerated,
}: {
  note: Note
  title: string
  aiIllustrationEnabled: boolean
  onNoteIllustrationGenerated?: (noteId: string) => void | Promise<void>
}) {
  const { t } = useLanguage()
  const [busy, setBusy] = useState(false)
  const img = getNoteFeedImage(note)

  const handleGenerateSvg = async (e: React.MouseEvent) => {
    e.stopPropagation()
    if (!aiIllustrationEnabled || busy || img) return
    setBusy(true)
    try {
      const res = await generateNoteIllustrationSvg(note.id, { skipRevalidation: true })
      if (!res.ok) {
        toast.error(res.error)
      } else {
        toast.success(t('notes.illustrationGenerated') || 'Illustration générée')
        await onNoteIllustrationGenerated?.(note.id)
      }
    } finally {
      setBusy(false)
    }
  }

  return (
    <div className={cn('relative shrink-0', img || note.illustrationSvg ? 'w-24 sm:w-32 aspect-[4/3] overflow-hidden rounded-md bg-muted/30' : 'flex w-11 flex-col items-center gap-1')}>
      {img ? (
        <img
          src={img}
          alt=""
          className="w-full h-full object-cover"
        />
      ) : note.illustrationSvg ? (
        <div
          className="w-full h-full flex items-center justify-center bg-muted/30 p-2 [&_svg]:max-w-full [&_svg]:max-h-full [&_svg]:w-auto [&_svg]:h-auto"
          // SVG déjà sanitisé côté serveur (note-illustration.ts)
          dangerouslySetInnerHTML={{ __html: sanitizeIllustrationSvg(note.illustrationSvg) }}
          aria-hidden
        />
      ) : (
        <>
          <span className="flex h-11 w-11 items-center justify-center rounded-md bg-brand-accent/10 text-brand-accent" aria-hidden>
            <FileText size={22} strokeWidth={1.5} />
          </span>
          {aiIllustrationEnabled && (
            <button
              type="button"
              aria-label={t('notes.generateIllustration') || 'Générer une illustration IA'}
              title={t('notes.generateIllustration') || 'Générer une illustration IA'}
              className="flex h-11 w-11 items-center justify-center rounded-md text-brand-accent transition-colors hover:bg-brand-accent/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-accent"
              onClick={handleGenerateSvg}
              disabled={busy}
            >
              {busy ? <Loader2 className="h-4 w-4 animate-spin" /> : <Sparkles className="h-4 w-4 text-primary" />}
            </button>
          )}
        </>
      )}
    </div>
  )
}

function NoteTag({ labelName, allLabels }: { labelName: string; allLabels: any[] }) {
  const labelDef = allLabels?.find(l => l.name === labelName)
  const isAI = labelDef?.type === 'ai'
  
  return (
    <div className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-paper dark:bg-white/5 text-[9px] font-bold uppercase tracking-[0.15em] text-muted-foreground border border-border/40">
      {isAI && <Sparkles size={8} className="text-brand-accent" />}
      {labelName}
    </div>
  )
}

export function NotesEditorialView({
  notes,
  onOpen,
  notebookName,
  onOpenHistory,
  onTogglePin,
  onDeleteNote,
  onArchiveNote,
  onMoveToNotebook,
  onNotePatch,
  onNoteIllustrationGenerated,
  selection,
}: NotesEditorialViewProps) {
  const { t, language } = useLanguage()
  const { data: session } = useSession()
  const { data: allLabels } = useLabelsQuery()
  const hydrated = useHydrated()
  const [aiIllustrationEnabled, setAiIllustrationEnabled] = useState(false)

  useEffect(() => {
    if (!session?.user?.id) {
      setAiIllustrationEnabled(false)
      return
    }
    getAISettings(session.user.id)
      .then((s) => setAiIllustrationEnabled(s.paragraphRefactor !== false))
      .catch(() => setAiIllustrationEnabled(false))
  }, [session?.user?.id])

  return (
    <div className="mx-auto w-full min-w-0 max-w-3xl divide-y divide-border/50">
      <AnimatePresence>
        {notes.map((note: Note, index: number) => {
          const title = getNoteDisplayTitle(note, t('notes.untitled') || 'Untitled')
          const excerpt = getNotePlainExcerpt(note)
          const dateStr = formatNoteDate(note.createdAt, language)
          const editorialRtl = language === 'fa' || language === 'ar'
          const dateDir = dateTextDirection(language)
          const dateLang = language === 'fa' ? 'fa' : language === 'ar' ? 'ar' : undefined

          return (
            <motion.article
              key={note.id}
              initial={hydrated ? { opacity: 0, y: 20 } : false}
              animate={{ opacity: 1, y: 0 }}
              transition={hydrated ? { delay: 0.05 * index, duration: 0.6 } : { duration: 0 }}
              className="min-w-0 space-y-3 group cursor-pointer relative py-5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-accent"
              onClick={() => onOpen(note)}
              onKeyDown={(e) => { if (e.key === 'Enter') onOpen(note) }}
              tabIndex={0}
              role="button"
            >
              {/* Date / breadcrumb — isolated bidi so Latin notebook name + Jalali date don’t reorder wrongly */}
              <div
                className="pe-12 text-xs font-medium text-muted-foreground"
                dir={editorialRtl ? 'rtl' : 'ltr'}
              >
                {notebookName ? (
                  <>
                    <bdi className={cn(editorialRtl && 'uppercase tracking-[0.2em]')} dir="auto">{notebookName}</bdi>
                    <span className="mx-1.5 select-none text-muted-foreground/80" aria-hidden>
                      —
                    </span>
                    <bdi dir={dateDir} lang={dateLang}>
                      {dateStr}
                    </bdi>
                  </>
                ) : (
                  <bdi dir={dateDir} lang={dateLang}>
                    {dateStr}
                  </bdi>
                )}
              </div>

              {/* Actions menu — absolutely positioned at top-right */}
              <div
                className="absolute top-3 end-0 opacity-100 md:opacity-0 md:group-hover:opacity-100 focus-within:opacity-100 transition-opacity"
                onClick={e => e.stopPropagation()}
              >
                <EditorialNoteMenu
                  note={note}
                  onOpen={onOpen}
                  onOpenHistory={onOpenHistory}
                  onTogglePin={onTogglePin}
                  onDeleteNote={onDeleteNote}
                  onArchiveNote={onArchiveNote}
                  onMoveToNotebook={onMoveToNotebook}
                  onNotePatch={onNotePatch}
                />
              </div>

              <h2 className="font-memento-serif text-lg sm:text-xl leading-snug font-medium text-foreground flex items-start gap-2">
                <span className="inline-flex items-start gap-2 min-w-0 flex-1">
                  {selection && (
                    <NoteSelectCheckbox
                      checked={selection.selectedIds.has(note.id)}
                      onToggle={() => selection.onToggle(note.id)}
                      label={t('notes.selectNote')}
                    />
                  )}
                  {note.isPinned && <Pin size={14} className="text-amber-500 fill-amber-500 shrink-0" />}
                  {note.historyEnabled && <History size={14} className="text-emerald-500 shrink-0" />}
                  <span className="min-w-0 break-words [overflow-wrap:anywhere]">{title}</span>
                </span>
                <span className="opacity-0 group-hover:opacity-30 transition-opacity shrink-0">
                  <ChevronRight size={20} />
                </span>
              </h2>

              <div className="flex gap-3 sm:gap-4 items-start min-w-0">
                <EditorialThumbnail
                  note={note}
                  title={title}
                  aiIllustrationEnabled={aiIllustrationEnabled}
                  onNoteIllustrationGenerated={onNoteIllustrationGenerated}
                />
                <div className="min-w-0 space-y-2 flex-1">
                  {note.labels && note.labels.length > 0 && (
                    <div className="flex flex-wrap gap-2">
                      {note.labels.slice(0, 2).map((labelName) => (
                        <NoteTag key={labelName} labelName={labelName} allLabels={allLabels || []} />
                      ))}
                    </div>
                  )}
                  {excerpt ? (
                    <p className="text-sm leading-relaxed text-foreground/80 line-clamp-2 break-words [overflow-wrap:anywhere]">
                      {excerpt}
                    </p>
                  ) : (
                    <p className="text-sm italic text-muted-foreground">{t('notes.noContent')}</p>
                  )}
                  <span className="text-xs text-brand-accent font-medium inline-flex items-center gap-1">
                    {t('notes.readMore') || 'Read more'}
                    <ChevronRight size={10} />
                  </span>
                </div>
              </div>
            </motion.article>
          )
        })}
      </AnimatePresence>
    </div>
  )
}
