import { useEffect, useRef, useState } from 'react'
import { Link } from 'react-router'
import type { AppBskyActorDefs } from '@atproto/api'
import type { OAuthSession } from '@atproto/oauth-client-browser'
import { useAuth } from '~/lib/auth-context'
import { useData } from '~/lib/data-context'
import {
  updatePublication,
  deletePublication,
  type Post,
  type Publication,
} from '~/lib/api-client'
import PostList from '~/components/PostList'
import BioText from '~/components/BioText'
import CreatePublication from '~/components/CreatePublication'
import Avatar from '~/components/Avatar'
import CenteredMessage from '~/components/CenteredMessage'
import Spinner from '~/components/Spinner'
import type { Route } from './+types/home'
import { SITE_NAME, TYPEAHEAD_URL } from '~/lib/site-config'

export function meta({}: Route.MetaArgs) {
  return [{ title: SITE_NAME }, { name: 'description', content: SITE_NAME }]
}

export default function Home() {
  const { session, loading, error } = useAuth()

  if (loading) return <LoadingScreen />
  if (error) return <ErrorScreen message={error} />
  if (session) return <ProfileScreen session={session} />
  return <LoginScreen />
}

function LoadingScreen() {
  return (
    <div className="flex-1 flex items-center justify-center">
      <Spinner />
    </div>
  )
}

function ErrorScreen({ message }: { message: string }) {
  const { signOut } = useAuth()
  return <CenteredMessage message={message} error action={{ label: 'Start over', onClick: signOut }} />
}

type TypeaheadActor = {
  did: string
  handle: string
  displayName?: string
  avatar?: string
}

function LoginScreen() {
  const { signIn } = useAuth()
  const [handle, setHandle] = useState('')
  const [pending, setPending] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [suggestions, setSuggestions] = useState<TypeaheadActor[]>([])
  const [showSuggestions, setShowSuggestions] = useState(false)
  const [activeIndex, setActiveIndex] = useState(-1)
  const [fetching, setFetching] = useState(false)
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  useEffect(() => () => { if (debounceRef.current) clearTimeout(debounceRef.current) }, [])

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!handle.trim()) return
    setPending(true)
    setError(null)
    try {
      await signIn(handle.trim())
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Sign in failed')
      setPending(false)
    }
  }

  function onHandleChange(e: React.ChangeEvent<HTMLInputElement>) {
    const value = e.target.value
    setHandle(value)
    setActiveIndex(-1)
    if (debounceRef.current) clearTimeout(debounceRef.current)
    const q = value.trim()
    if (!q || q.startsWith('did:')) {
      setSuggestions([])
      setShowSuggestions(false)
      setFetching(false)
      return
    }
    setFetching(true)
    debounceRef.current = setTimeout(async () => {
      try {
        const res = await fetch(
          `${TYPEAHEAD_URL}/xrpc/app.bsky.actor.searchActorsTypeahead?q=${encodeURIComponent(q)}&limit=6`,
          { headers: { 'X-Client': 'lemma' } },
        )
        if (!res.ok) return
        const data = await res.json() as { actors: TypeaheadActor[] }
        const actors = data.actors ?? []
        setSuggestions(actors)
        setShowSuggestions(actors.length > 0)
      } catch {
        // fail silently — typeahead is non-critical
      } finally {
        setFetching(false)
      }
    }, 300)
  }

  function selectSuggestion(actor: TypeaheadActor) {
    setHandle(actor.handle)
    setSuggestions([])
    setShowSuggestions(false)
    setActiveIndex(-1)
  }

  function onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (!showSuggestions || suggestions.length === 0) return
    if (e.key === 'ArrowDown') {
      e.preventDefault()
      setActiveIndex((i) => Math.min(i + 1, suggestions.length - 1))
    } else if (e.key === 'ArrowUp') {
      e.preventDefault()
      setActiveIndex((i) => Math.max(i - 1, -1))
    } else if (e.key === 'Enter' && activeIndex >= 0) {
      e.preventDefault()
      selectSuggestion(suggestions[activeIndex])
    } else if (e.key === 'Escape') {
      setShowSuggestions(false)
      setActiveIndex(-1)
    }
  }

  return (
    <div className="flex-1 flex flex-col md:flex-row">

      {/* ── Brand panel ─────────────────────────────────────────────────────── */}
      <div className="relative overflow-hidden bg-[#151210] md:w-[48%] md:min-h-full flex flex-col justify-between p-8 md:p-14 min-h-[220px]">

        {/* Giant λ watermark */}
        <div className="absolute inset-0 flex items-end justify-end pointer-events-none select-none overflow-hidden" aria-hidden>
          <span className="font-display font-bold text-[52vw] md:text-[34vw] leading-none text-white/[0.04] translate-x-[10%] translate-y-[8%]">λ</span>
        </div>

        {/* Wordmark */}
        <div className="relative z-10 flex items-center gap-2">
          {/* <span className="font-display text-2xl font-bold text-white leading-none">λ</span> */}
          <span className="font-display text-lg text-white/40 font-normal tracking-wide">{SITE_NAME}</span>
          <span className="text-[9px] font-semibold text-white/30 border border-white/20 rounded px-1.5 py-0.5 leading-none">alpha</span>
        </div>

        {/* Hero text — hidden on small screens to keep the panel compact */}
        <div className="relative z-10 hidden md:block space-y-4">
          <p className="font-display text-4xl xl:text-5xl font-semibold text-white leading-[1.15]">
            Own your words.
          </p>
          <p className="text-white/40 text-sm leading-relaxed max-w-xs font-sans">
            A blog publishing platform built on the open Atmosphere network. Experience features built for scientists, artists, engineers, journalists, and everyone with something to say.
          </p>
        </div>
      </div>

      {/* ── Form panel ──────────────────────────────────────────────────────── */}
      <div className="flex-1 flex items-center justify-center px-8 py-12 md:py-0 bg-[#FAF9F6] dark:bg-[#1C1917]">
        <div className="w-full max-w-sm space-y-8">

          {/* Heading */}
          <div className="space-y-1">
            <h1 className="font-display text-3xl font-semibold text-[#1A1614] dark:text-white tracking-tight">
              Sign in
            </h1>
            <p className="text-sm text-[#7C7268] dark:text-[#A8A29E]">
              Use your Atmosphere handle to continue
            </p>
          </div>

          {/* Form */}
          <form onSubmit={handleSubmit} className="space-y-3">
            <div className="relative space-y-1.5">
              <div className="flex items-center justify-between">
                <label
                  htmlFor="handle"
                  className="block text-xs font-semibold uppercase tracking-widest text-[#9E9389] dark:text-[#78716C]"
                >
                  Handle
                </label>
                {fetching && (
                  <span className="flex items-center gap-[3px]" aria-hidden>
                    {[0, 1, 2].map((j) => (
                      <span
                        key={j}
                        className="typeahead-dot w-[3px] h-[3px] rounded-full bg-[#9E9389] dark:bg-[#78716C]"
                        style={{ animationDelay: `${j * 0.18}s` }}
                      />
                    ))}
                  </span>
                )}
              </div>
              <input
                id="handle"
                type="text"
                value={handle}
                onChange={onHandleChange}
                onKeyDown={onKeyDown}
                onFocus={() => { if (suggestions.length > 0) setShowSuggestions(true) }}
                onBlur={() => setTimeout(() => setShowSuggestions(false), 150)}
                placeholder="you.bsky.social"
                autoComplete="off"
                autoCapitalize="none"
                autoCorrect="off"
                disabled={pending}
                className="w-full rounded-lg border border-[#E5E0D8] dark:border-[#2E2925] bg-white dark:bg-[#141210] px-4 py-3 text-sm text-[#1A1614] dark:text-white placeholder-[#C4BAB0] dark:placeholder-[#57504A] focus:outline-none focus:ring-2 focus:ring-[#1A1614] dark:focus:ring-white/30 focus:border-transparent disabled:opacity-50 transition-all"
              />
              {showSuggestions && suggestions.length > 0 && (
                <ul
                  role="listbox"
                  className="absolute z-10 top-full mt-2 w-full bg-white dark:bg-[#1A1714] border border-[#E5E0D8] dark:border-[#2E2925] shadow-2xl overflow-hidden divide-y divide-[#F0EDE8] dark:divide-[#252018]"
                >
                  {suggestions.map((actor, i) => (
                    <li
                      key={actor.did}
                      role="option"
                      aria-selected={i === activeIndex}
                      onMouseDown={() => selectSuggestion(actor)}
                      className={`typeahead-item flex items-center gap-3 px-4 py-3 cursor-pointer border-l-[3px] transition-colors duration-150 ${
                        i === activeIndex
                          ? 'bg-[#F5F1EC] dark:bg-[#231F1C] border-l-[#1A1614] dark:border-l-white'
                          : 'border-l-transparent hover:bg-[#FAF8F5] dark:hover:bg-[#201D1A] hover:border-l-[#C4BAB0] dark:hover:border-l-[#57504A]'
                      }`}
                      style={{ animationDelay: `${i * 40}ms` }}
                    >
                      <div className="shrink-0">
                        {actor.avatar ? (
                          <img
                            src={actor.avatar}
                            alt=""
                            className="w-8 h-8 rounded-full object-cover ring-1 ring-[#E5E0D8] dark:ring-[#2E2925]"
                          />
                        ) : (
                          <div className="w-8 h-8 rounded-full bg-[#EDE9E4] dark:bg-[#2E2925] ring-1 ring-[#E5E0D8] dark:ring-[#3A342F] flex items-center justify-center">
                            <span className="font-display italic text-xs text-[#9E9389] dark:text-[#78716C]">λ</span>
                          </div>
                        )}
                      </div>
                      <div className="min-w-0 flex-1">
                        {actor.displayName ? (
                          <>
                            <p className="font-display text-sm font-medium text-[#1A1614] dark:text-white truncate leading-tight">{actor.displayName}</p>
                            <p className="text-[10px] tracking-widest uppercase text-[#9E9389] dark:text-[#78716C] truncate mt-0.5">@{actor.handle}</p>
                          </>
                        ) : (
                          <p className="font-display text-sm font-medium text-[#1A1614] dark:text-white truncate leading-tight">@{actor.handle}</p>
                        )}
                      </div>
                    </li>
                  ))}
                </ul>
              )}
            </div>

            {error && <p className="text-sm text-red-500">{error}</p>}

            <p className="text-xs text-center text-[#9E9389] dark:text-[#78716C]">
              By continuing you accept the{' '}
              <Link to="/tos" className="underline hover:text-[#1A1614] dark:hover:text-white transition-colors">Terms of Service</Link>
              {' '}and{' '}
              <Link to="/privacy" className="underline hover:text-[#1A1614] dark:hover:text-white transition-colors">Privacy Policy</Link>
            </p>
            <button
              type="submit"
              disabled={pending || !handle.trim()}
              className="w-full rounded-lg bg-[#1A1614] dark:bg-white hover:bg-[#2E2925] dark:hover:bg-[#F0EDE8] disabled:opacity-35 disabled:cursor-not-allowed px-4 py-3 text-sm font-semibold text-white dark:text-[#1A1614] transition-colors"
            >
              {pending ? 'Redirecting…' : 'Accept & Sign in'}
            </button>
          </form>

          {/* Sign up footer */}
          <div className="pt-2 border-t border-[#E5E0D8] dark:border-[#2E2925]">
            <p className="text-sm text-[#7C7268] dark:text-[#78716C]">
              New to the Atmosphere?{' '}
              <a
                href="https://bsky.app"
                target="_blank"
                rel="noopener noreferrer"
                className="font-medium text-[#1A1614] dark:text-white hover:underline underline-offset-2"
              >
                Create an account on Bluesky
              </a>
            </p>
          </div>

        </div>
      </div>

    </div>
  )
}

function ProfileScreen({ session }: { session: OAuthSession }) {
  const { signOut } = useAuth()
  const { publications, setPublications } = useData()
  const [profile, setProfile] = useState<AppBskyActorDefs.ProfileViewDetailed | null>(null)
  const [profileError, setProfileError] = useState<string | null>(null)

  useEffect(() => {
    fetch(
      `https://api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${encodeURIComponent(session.sub)}`,
    )
      .then((res) => {
        if (!res.ok) throw new Error(`Failed to load profile: ${res.status}`)
        return res.json() as Promise<AppBskyActorDefs.ProfileViewDetailed>
      })
      .then((data) => setProfile(data))
      .catch((err: unknown) => {
        setProfileError(err instanceof Error ? err.message : 'Failed to load profile')
      })
  }, [session])

  if (profileError) {
    return <CenteredMessage message={profileError} error action={{ label: 'Sign out', onClick: signOut }} />
  }

  if (!profile) return <LoadingScreen />

  return (
    <div className="flex-1 p-4 md:p-8 lg:p-10">
      <div className="max-w-5xl mx-auto">
        <div className="flex flex-col md:flex-row gap-8 md:gap-10 lg:gap-16">

          {/* ── Sidebar ─────────────────────────────────────────────────────── */}
          <aside className="md:w-52 lg:w-60 shrink-0">
            <div className="md:sticky md:top-8 relative">

              {/* Decorative λ watermark */}
              <span
                className="absolute -bottom-4 -right-2 font-display text-[9rem] leading-none text-stone-900/[0.04] dark:text-white/[0.04] pointer-events-none select-none hidden md:block"
                aria-hidden
              >
                λ
              </span>

              {/* Mobile: compact horizontal identity row */}
              <div className="flex items-center gap-4 md:flex-col md:items-start md:gap-5 mb-6 md:mb-0 relative z-10">
                <Avatar src={profile.avatar} size="lg" />
                <div className="min-w-0 flex-1">
                  {profile.displayName && (
                    <p className="font-display font-semibold text-stone-900 dark:text-white truncate text-lg md:text-2xl leading-tight">
                      {profile.displayName}
                    </p>
                  )}
                  <p className="text-sm text-stone-400 dark:text-stone-500 truncate mt-0.5">@{profile.handle}</p>
                </div>
              </div>

              {/* Desktop-only: bio + sign out */}
              <div className="hidden md:flex md:flex-col md:gap-5 md:mt-6 relative z-10">
                {profile.description && (
                  <BioText
                    text={profile.description}
                    className="text-sm text-stone-500 dark:text-stone-400 leading-relaxed line-clamp-6 whitespace-pre-wrap"
                  />
                )}

                <button
                  onClick={() => signOut()}
                  className="text-sm text-stone-400 dark:text-stone-600 hover:text-stone-700 dark:hover:text-stone-400 transition-colors self-start"
                >
                  Sign out
                </button>
              </div>
            </div>
          </aside>

          {/* ── Main content ─────────────────────────────────────────────────── */}
          <div className="flex-1 min-w-0 space-y-6">
            {publications === undefined ? (
              <div className="flex justify-center py-8">
                <Spinner size="md" />
              </div>
            ) : publications.length === 0 ? (
              <CreatePublication
                session={session}
                onCreated={(pub) => setPublications([pub])}
              />
            ) : (
              <>
                <PublicationsManager
                  session={session}
                  publications={publications}
                  onPublicationsChange={setPublications}
                />
                <BlogSection handle={profile.handle} publications={publications} />
              </>
            )}

            {/* Mobile: sign out */}
            <div className="md:hidden pt-2 border-t border-stone-200 dark:border-stone-800">
              <button
                onClick={() => signOut()}
                className="text-sm text-stone-400 hover:text-stone-600 dark:hover:text-stone-400 transition-colors"
              >
                Sign out
              </button>
            </div>
          </div>

        </div>
      </div>
    </div>
  )
}

function BlogSection({
  handle,
  publications,
}: {
  handle: string
  publications: Publication[]
}) {
  const { posts } = useData()
  const [selectedPubAtUri, setSelectedPubAtUri] = useState<string>('all')

  const publishedPosts = posts?.filter((p) => p.visibility === 'published') ?? null
  const draftPosts = posts?.filter((p) => p.visibility === 'draft') ?? null

  const filteredPublished = publishedPosts === null ? null
    : selectedPubAtUri === 'all' ? publishedPosts
    : publishedPosts.filter((p) => p.site === selectedPubAtUri)

  const articleCount = filteredPublished?.length ?? null
  const draftCount = draftPosts?.length ?? 0

  return (
    <div className="space-y-8">
      {draftCount > 0 && draftPosts !== null && (
        <div className="space-y-4">
          <div className="flex items-baseline gap-2.5">
            <span className="font-display text-4xl font-bold text-stone-900 dark:text-white tabular-nums leading-none">{draftCount}</span>
            <span className="text-[10px] font-bold uppercase tracking-widest text-stone-400 dark:text-stone-600">
              {draftCount === 1 ? 'draft' : 'drafts'}
            </span>
          </div>
          <PostList posts={draftPosts} handle={handle} />
        </div>
      )}

      <div className="space-y-5">
        <div className="flex items-center justify-between gap-4">
          <div>
            {articleCount === null ? (
              <h2 className="font-display text-xl font-semibold text-stone-900 dark:text-white">Articles</h2>
            ) : articleCount === 0 ? (
              <h2 className="font-display text-xl font-semibold text-stone-400 dark:text-stone-600">No articles yet</h2>
            ) : (
              <div className="flex items-baseline gap-2.5">
                <span className="font-display text-4xl font-bold text-stone-900 dark:text-white tabular-nums leading-none">{articleCount}</span>
                <span className="text-[10px] font-bold uppercase tracking-widest text-stone-400 dark:text-stone-600">
                  {articleCount === 1 ? 'article' : 'articles'}
                </span>
              </div>
            )}
          </div>
          <div className="flex items-center gap-2">
            {publications.length > 1 && (
              <select
                value={selectedPubAtUri}
                onChange={(e) => setSelectedPubAtUri(e.target.value)}
                className="rounded-lg border border-stone-200 dark:border-stone-700 bg-white dark:bg-stone-800 px-3 py-1.5 text-sm text-stone-700 dark:text-stone-300 focus:outline-none focus:ring-2 focus:ring-stone-900 dark:focus:ring-stone-100"
              >
                <option value="all">All publications</option>
                {publications.map((pub) => (
                  <option key={pub.sk} value={pub.atUri}>
                    {pub.name} — {new URL(pub.url).host}
                  </option>
                ))}
              </select>
            )}
            <Link
              to="/kanban"
              className="rounded-lg border border-stone-200 dark:border-stone-700 px-3 py-1.5 text-sm text-stone-500 dark:text-stone-400 hover:text-stone-900 dark:hover:text-white hover:border-stone-400 dark:hover:border-stone-500 transition-colors"
            >
              New Kanban Board
            </Link>
          </div>
        </div>

        {filteredPublished === null && (
          <div className="flex justify-center py-4">
            <Spinner size="sm" />
          </div>
        )}

        <PostList posts={filteredPublished} handle={handle} />
      </div>
    </div>
  )
}

function PublicationsManager({
  session,
  publications,
  onPublicationsChange,
}: {
  session: OAuthSession
  publications: Publication[]
  onPublicationsChange: (pubs: Publication[]) => void
}) {
  const [editingRkey, setEditingRkey] = useState<string | null>(null)
  const [confirmDeleteRkey, setConfirmDeleteRkey] = useState<string | null>(null)
  const [showCreate, setShowCreate] = useState(false)
  const [editName, setEditName] = useState('')
  const [editDescription, setEditDescription] = useState('')
  const [editShowInDiscover, setEditShowInDiscover] = useState(false)
  const [pending, setPending] = useState(false)
  const [error, setError] = useState<string | null>(null)

  function startEdit(pub: Publication) {
    setEditingRkey(pub.sk.slice(4))
    setEditName(pub.name)
    setEditDescription(pub.description ?? '')
    setEditShowInDiscover(pub.preferences.showInDiscover)
    setConfirmDeleteRkey(null)
    setShowCreate(false)
    setError(null)
  }

  async function handleUpdate(e: React.FormEvent) {
    e.preventDefault()
    if (!editingRkey) return
    setPending(true)
    setError(null)
    try {
      await updatePublication(session, editingRkey, {
        name: editName.trim(),
        description: editDescription.trim() || undefined,
        showInDiscover: editShowInDiscover,
      })
      onPublicationsChange(publications.map((p) =>
        p.sk === `pub#${editingRkey}`
          ? { ...p, name: editName.trim(), description: editDescription.trim() || undefined, preferences: { showInDiscover: editShowInDiscover } }
          : p,
      ))
      setEditingRkey(null)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Update failed')
    } finally {
      setPending(false)
    }
  }

  async function handleDelete(rkey: string) {
    setPending(true)
    setError(null)
    try {
      await deletePublication(session, rkey)
      onPublicationsChange(publications.filter((p) => p.sk !== `pub#${rkey}`))
      setConfirmDeleteRkey(null)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Delete failed')
    } finally {
      setPending(false)
    }
  }

  const inputClass =
    'w-full rounded-lg border border-stone-300 dark:border-stone-600 bg-white dark:bg-stone-800 px-3 py-2 text-sm text-stone-900 dark:text-white placeholder-stone-400 focus:outline-none focus:ring-2 focus:ring-stone-900 dark:focus:ring-stone-100 disabled:opacity-50'

  return (
    <div className="space-y-3 pt-6 border-t border-stone-200 dark:border-stone-800">
      <div className="flex items-center justify-between">
        <h2 className="font-display text-xl font-semibold text-stone-900 dark:text-white">Publications</h2>
        <button
          type="button"
          onClick={() => { setShowCreate(true); setEditingRkey(null); setConfirmDeleteRkey(null); setError(null) }}
          className="text-sm font-medium text-stone-500 dark:text-stone-400 hover:text-stone-900 dark:hover:text-white transition-colors"
        >
          + New
        </button>
      </div>

      {error && <p className="text-sm text-red-500">{error}</p>}

      <ul className="space-y-2.5">
        {publications.map((pub) => {
          const rkey = pub.sk.slice(4)
          const isEditing = editingRkey === rkey
          const isConfirming = confirmDeleteRkey === rkey

          if (isEditing) {
            return (
              <li key={pub.sk} className="rounded-lg border border-stone-300 dark:border-stone-600 bg-white dark:bg-stone-900/40 p-4">
                <form onSubmit={handleUpdate} className="space-y-3">
                  <input type="text" value={editName} onChange={(e) => setEditName(e.target.value)} placeholder="Name" disabled={pending} className={inputClass} />
                  <input type="text" value={editDescription} onChange={(e) => setEditDescription(e.target.value)} placeholder="Description (optional)" disabled={pending} className={inputClass} />
                  <label className="flex items-center gap-2 text-sm text-stone-700 dark:text-stone-300 cursor-pointer">
                    <input type="checkbox" checked={editShowInDiscover} onChange={(e) => setEditShowInDiscover(e.target.checked)} disabled={pending} className="rounded border-stone-300 dark:border-stone-600" />
                    Discover on other platforms
                  </label>
                  <div className="flex gap-2">
                    <button type="submit" disabled={pending || !editName.trim()} className="rounded-lg bg-stone-900 dark:bg-stone-100 px-4 py-2 text-sm font-semibold text-white dark:text-stone-900 disabled:opacity-50 hover:bg-stone-700 dark:hover:bg-stone-200 transition-colors">
                      {pending ? 'Saving…' : 'Save'}
                    </button>
                    <button type="button" onClick={() => setEditingRkey(null)} disabled={pending} className="rounded-lg border border-stone-200 dark:border-stone-700 px-4 py-2 text-sm font-medium text-stone-600 dark:text-stone-400 hover:bg-stone-50 dark:hover:bg-stone-800 transition-colors">
                      Cancel
                    </button>
                  </div>
                </form>
              </li>
            )
          }

          return (
            <li key={pub.sk} className="group rounded-lg border border-stone-200 dark:border-stone-700/80 bg-white dark:bg-stone-900/40 overflow-hidden hover:border-stone-300 dark:hover:border-stone-600 hover:shadow-md hover:-translate-y-px transition-all duration-150">
              {isConfirming ? (
                <div className="px-4 py-3.5 space-y-2">
                  <p className="text-sm text-stone-700 dark:text-stone-300">
                    Delete <span className="font-medium">{pub.name}</span>? This can't be undone.
                  </p>
                  <div className="flex gap-2">
                    <button onClick={() => handleDelete(rkey)} disabled={pending} className="rounded-lg bg-red-600 hover:bg-red-700 px-3 py-1.5 text-sm font-medium text-white disabled:opacity-50 transition-colors">
                      {pending ? 'Deleting…' : 'Delete'}
                    </button>
                    <button onClick={() => setConfirmDeleteRkey(null)} disabled={pending} className="rounded-lg border border-stone-200 dark:border-stone-700 px-3 py-1.5 text-sm font-medium text-stone-600 dark:text-stone-400 hover:bg-stone-50 dark:hover:bg-stone-800 transition-colors">
                      Cancel
                    </button>
                  </div>
                </div>
              ) : (
                <div className="flex items-center justify-between gap-3 px-4 py-3.5 min-h-[5rem]">
                  <div className="min-w-0">
                    <p className="font-display text-base font-medium text-stone-900 dark:text-white truncate leading-snug">{pub.name}</p>
                    <p className="text-sm text-stone-400 dark:text-stone-500 truncate mt-1">{new URL(pub.url).host}</p>
                    {pub.description && (
                      <p className="text-sm text-stone-400 dark:text-stone-500 truncate mt-0.5">{pub.description}</p>
                    )}
                  </div>
                  <div className="flex items-center gap-3 shrink-0">
                    <button onClick={() => startEdit(pub)} className="text-sm text-stone-400 dark:text-stone-500 hover:text-stone-900 dark:hover:text-white transition-colors">
                      Edit
                    </button>
                    <button onClick={() => { setConfirmDeleteRkey(rkey); setEditingRkey(null); setShowCreate(false) }} className="text-sm text-stone-400 dark:text-stone-500 hover:text-red-600 dark:hover:text-red-400 transition-colors">
                      Delete
                    </button>
                  </div>
                </div>
              )}
            </li>
          )
        })}
      </ul>

      {showCreate && (
        <CreatePublication
          session={session}
          onCreated={(pub) => {
            onPublicationsChange([...publications, pub])
            setShowCreate(false)
          }}
          onCancel={() => setShowCreate(false)}
        />
      )}
    </div>
  )
}
