'use client'

import { useCallback, useEffect, useState } from 'react'
import Link from 'next/link'
import { Target, Circle, CheckCircle2, X, Plus, ChevronDown, ChevronRight, ClipboardList } from 'lucide-react'

interface ReminderPin { pinId: string; kind: 'reminder'; id: string; title: string; done: boolean; dueDate: string | null; list: string | null }
interface ItemPin { pinId: string; kind: 'item'; id: string; title: string; done: boolean; list: string | null; listId: string }
interface ListItem { id: string; title: string; done: boolean }
interface ListPin { pinId: string; kind: 'list'; id: string; name: string; items: ListItem[] }
type Pin = ReminderPin | ItemPin | ListPin
type TaskPin = ReminderPin | ItemPin

// "Today's Focus" — a pinboard, not a list of its own. Each pin references a
// reminder, a single list item (which stays in its list), or a whole list
// (shown expandable). Pin things by dragging them here; typing adds a reminder
// and pins it. Removing a pin never deletes the underlying item.
export function Focus() {
  const [pins, setPins] = useState<Pin[]>([])
  const [draft, setDraft] = useState('')
  const [showAllDone, setShowAllDone] = useState(false)
  const [dropHover, setDropHover] = useState(false)
  const [expanded, setExpanded] = useState<Set<string>>(new Set())

  const load = useCallback(async () => {
    const res = await fetch('/api/focus', { cache: 'no-store' })
    if (res.ok) setPins((await res.json()).pins || [])
  }, [])

  useEffect(() => {
    load()
    const onUp = () => load()
    window.addEventListener('capture-uploaded', onUp)
    window.addEventListener('focus-refresh', onUp)
    const t = setInterval(load, 8000)
    return () => { window.removeEventListener('capture-uploaded', onUp); window.removeEventListener('focus-refresh', onUp); clearInterval(t) }
  }, [load])

  const tasks = pins.filter((p): p is TaskPin => p.kind === 'reminder' || p.kind === 'item')
  const lists = pins.filter((p): p is ListPin => p.kind === 'list')

  const add = async () => {
    if (!draft.trim()) return
    await fetch('/api/focus', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: draft.trim() }) })
    setDraft(''); load()
  }
  // Checking off a pin acts on the canonical record: a reminder (pushed to
  // Apple) or the list item it points at.
  const toggleTask = async (p: TaskPin) => {
    const next = !p.done
    setPins(ps => ps.map(x => x.pinId === p.pinId ? { ...x, done: next } : x))
    if (p.kind === 'reminder') {
      await fetch(`/api/reminders/${p.id}/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ completed: next }) })
    } else {
      await fetch(`/api/checklist-items/${p.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ done: next }) })
      window.dispatchEvent(new Event('lists-refresh')) // the item lives in a list too
    }
    load()
  }
  const toggleListItem = async (listId: string, item: ListItem) => {
    const next = !item.done
    setPins(ps => ps.map(x => x.kind === 'list' && x.id === listId ? { ...x, items: x.items.map(i => i.id === item.id ? { ...i, done: next } : i) } : x))
    await fetch(`/api/checklist-items/${item.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ done: next }) })
    load()
  }
  const unpin = async (pinId: string) => {
    setPins(ps => ps.filter(p => p.pinId !== pinId))
    await fetch(`/api/focus/${pinId}`, { method: 'DELETE' })
    load()
  }
  const toggleExpand = (id: string) =>
    setExpanded(s => { const n = new Set(s); if (n.has(id)) n.delete(id); else n.add(id); return n })

  // Drop a reminder to pin it, a list item to pin it (it stays in its list),
  // or a whole list to pin it expanded.
  const onDrop = async (e: React.DragEvent) => {
    setDropHover(false)
    const pinFrom = async (key: string, field: 'reminderId' | 'checklistItemId' | 'checklistId') => {
      const raw = e.dataTransfer.getData(key)
      if (!raw) return false
      e.preventDefault()
      try {
        const { id } = JSON.parse(raw) as { id: string }
        if (id) { await fetch('/api/focus', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ [field]: id }) }); load() }
      } catch { /* ignore */ }
      return true
    }
    if (await pinFrom('application/x-reminder', 'reminderId')) return
    if (await pinFrom('application/x-checklist-item', 'checklistItemId')) return
    await pinFrom('application/x-checklist', 'checklistId')
  }
  const acceptsDrag = (e: React.DragEvent) =>
    e.dataTransfer.types.includes('application/x-reminder') ||
    e.dataTransfer.types.includes('application/x-checklist-item') ||
    e.dataTransfer.types.includes('application/x-checklist')

  const clearDone = async () => {
    const n = tasks.filter(p => p.done).length
    if (!confirm(`Unpin ${n} done item${n === 1 ? '' : 's'} from Focus? (The reminders/list items themselves stay.)`)) return
    await fetch('/api/focus?done=1', { method: 'DELETE' })
    load()
  }

  const anyDone = tasks.some(p => p.done)
  const openLeft = tasks.filter(p => !p.done).length

  // Open tasks always show; completed ones collapse to the most recent few.
  const DONE_SHOWN = 3
  const open = tasks.filter(p => !p.done)
  const done = tasks.filter(p => p.done)
  const hiddenDone = showAllDone ? 0 : Math.max(0, done.length - DONE_SHOWN)
  const visibleTasks = [...open, ...(showAllDone ? done : done.slice(0, DONE_SHOWN))]
  const empty = pins.length === 0

  return (
    <div
      onDragOver={e => { if (acceptsDrag(e)) { e.preventDefault(); setDropHover(true) } }}
      onDragLeave={() => setDropHover(false)}
      onDrop={onDrop}
      className={`rounded-2xl border p-4 space-y-2 transition-colors ${dropHover ? 'border-primary ring-2 ring-primary/30 bg-primary/10' : 'border-primary/25 bg-primary/5'}`}
    >
      <div className="flex items-center gap-2">
        <Link href="/focus" className="inline-flex items-center gap-2 hover:opacity-80">
          <Target className="h-4 w-4 text-primary" />
          <span className="text-sm font-semibold">Focus</span>
          <ChevronRight className="h-4 w-4 text-muted-foreground" />
        </Link>
        {!empty && (
          <span className="text-xs rounded-full bg-card border border-border px-2 py-0.5 text-muted-foreground">
            {openLeft} left
          </span>
        )}
        {anyDone && (
          <button onClick={clearDone} className="ml-auto text-xs text-muted-foreground hover:text-foreground">Clear done</button>
        )}
      </div>

      {!empty && (
        <ul className="space-y-1">
          {visibleTasks.map(p => (
            <li
              key={p.pinId}
              draggable={p.kind === 'reminder'}
              onDragStart={p.kind === 'reminder' ? e => {
                e.dataTransfer.setData('application/x-reminder', JSON.stringify({ id: p.id, title: p.title }))
                e.dataTransfer.effectAllowed = 'move'
              } : undefined}
              className="flex items-center gap-2 text-sm"
            >
              <button onClick={() => toggleTask(p)} className={p.done ? 'text-emerald-600' : 'text-muted-foreground hover:text-primary'} aria-label="Toggle done">
                {p.done ? <CheckCircle2 className="h-5 w-5" /> : <Circle className="h-5 w-5" />}
              </button>
              <span title={p.title} className={`min-w-0 flex-1 truncate ${p.done ? 'line-through text-muted-foreground' : ''}`}>
                {p.title}
                {p.list && (
                  <span className="ml-2 inline-flex items-center gap-1 text-xs text-muted-foreground align-middle">
                    {p.kind === 'item' && <ClipboardList className="h-3 w-3" />}{p.list}
                  </span>
                )}
              </span>
              <button onClick={() => unpin(p.pinId)} className="text-muted-foreground hover:text-destructive shrink-0" aria-label="Unpin from Focus" title="Remove from Focus (the original stays)">
                <X className="h-4 w-4" />
              </button>
            </li>
          ))}
          {hiddenDone > 0 && (
            <li>
              <button onClick={() => setShowAllDone(true)} className="w-full inline-flex items-center justify-center gap-1 text-xs text-muted-foreground py-1 hover:text-foreground">
                <ChevronDown className="h-3.5 w-3.5" /> {hiddenDone} more done
              </button>
            </li>
          )}

          {/* Pinned lists, each expandable in place. */}
          {lists.map(l => {
            const doneCount = l.items.filter(i => i.done).length
            const isOpen = expanded.has(l.id)
            const sorted = [...l.items].sort((a, b) => Number(a.done) - Number(b.done))
            return (
              <li key={l.pinId} className="space-y-1">
                <div className="flex items-center gap-1.5 rounded-xl border border-border bg-background/60 px-2 py-1.5">
                  <button onClick={() => toggleExpand(l.id)} className="p-0.5 rounded hover:bg-muted text-muted-foreground" aria-label={isOpen ? 'Collapse' : 'Expand'}>
                    {isOpen ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
                  </button>
                  <ClipboardList className="h-3.5 w-3.5 text-primary shrink-0" />
                  <Link href={`/list/${l.id}`} className="text-sm min-w-0 flex-1 truncate hover:underline">{l.name}</Link>
                  <span className="text-xs rounded-full bg-muted px-2 py-0.5 text-muted-foreground">{doneCount}/{l.items.length}</span>
                  <button onClick={() => unpin(l.pinId)} className="text-muted-foreground hover:text-destructive shrink-0" aria-label="Unpin list from Focus" title="Remove from Focus (the list stays)">
                    <X className="h-4 w-4" />
                  </button>
                </div>
                {isOpen && sorted.length > 0 && (
                  <ul className="pl-8 pr-1 space-y-1">
                    {sorted.map(i => (
                      <li key={i.id} className="flex items-center gap-2 text-sm">
                        <button onClick={() => toggleListItem(l.id, i)} className={i.done ? 'text-emerald-600' : 'text-muted-foreground hover:text-primary'} aria-label="Toggle done">
                          {i.done ? <CheckCircle2 className="h-4 w-4" /> : <Circle className="h-4 w-4" />}
                        </button>
                        <span title={i.title} className={`min-w-0 flex-1 truncate ${i.done ? 'line-through text-muted-foreground' : ''}`}>{i.title}</span>
                      </li>
                    ))}
                  </ul>
                )}
                {isOpen && sorted.length === 0 && <p className="pl-8 text-xs text-muted-foreground">Empty list.</p>}
              </li>
            )
          })}
        </ul>
      )}

      <div className="flex gap-2 pt-0.5">
        <input
          value={draft}
          onChange={e => setDraft(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') add() }}
          placeholder="Add to today…"
          className="flex-1 rounded-lg border border-input bg-background px-3 h-9 text-base focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
        />
        <button onClick={add} className="rounded-lg bg-primary text-primary-foreground px-3 h-9 inline-flex items-center" aria-label="Add">
          <Plus className="h-4 w-4" />
        </button>
      </div>
    </div>
  )
}
