import { useMemo, useState } from 'react'
import { api, type DocSummary, type Tag, type TagColor } from '../../api/client'
import { DocListItem } from './DocListItem'
import { SearchBox } from './SearchBox'
import { TagChip } from './TagChip'

interface Props {
  docs: DocSummary[]
  roster: Tag[]
  selectedId: string | null
  onSelect: (id: string) => void
  onCreate: () => void
  onDelete: (id: string) => void
  onDuplicate: (id: string) => void
  onToggleTag: (docId: string, tag: Tag) => void
  onCreateTag: (docId: string, name: string, color: TagColor) => void
}

// Sidebar sort orders. 'recent' keeps the server's updated_at-desc ordering.
type SortMode = 'recent' | 'title' | 'longest'
const SORTS: { value: SortMode; label: string }[] = [
  { value: 'recent', label: '最近 · Recent' },
  { value: 'title', label: '标题 · Title' },
  { value: 'longest', label: '字数 · Longest' },
]

// DocList is the sidebar: a cross-document search box, a tag filter bar, the New
// button, and the document browser (each row showing its tag chips).
export function DocList({
  docs,
  roster,
  selectedId,
  onSelect,
  onCreate,
  onDelete,
  onDuplicate,
  onToggleTag,
  onCreateTag,
}: Props) {
  // Active tag filter (null = show all). Cleared automatically if the tag
  // disappears from the roster.
  const [filterId, setFilterId] = useState<string | null>(null)
  const activeFilter = filterId && roster.some((t) => t.id === filterId) ? filterId : null
  const [sort, setSort] = useState<SortMode>('recent')

  const filtered = useMemo(() => {
    const base = activeFilter ? docs.filter((d) => d.tags.some((t) => t.id === activeFilter)) : docs
    if (sort === 'recent') return base // already updated_at-desc from the server
    const arr = [...base]
    if (sort === 'title') {
      arr.sort((a, b) =>
        (a.title || 'Untitled').localeCompare(b.title || 'Untitled', undefined, { sensitivity: 'base' }),
      )
    } else {
      arr.sort((a, b) => b.word_count - a.word_count)
    }
    return arr
  }, [docs, activeFilter, sort])

  // Only surface tags that are actually in use, so the filter bar stays tidy.
  const usedTags = useMemo(() => roster.filter((t) => (t.doc_count ?? 0) > 0), [roster])

  return (
    <aside
      className="flex h-full w-[280px] flex-col gap-2 p-3"
      style={{ borderRight: '1px solid var(--color-border)' }}
    >
      <SearchBox onSelect={onSelect} />

      {usedTags.length > 0 && (
        <div className="flex flex-wrap gap-1 pb-0.5">
          {usedTags.map((t) => (
            <TagChip
              key={t.id}
              tag={t}
              count={t.doc_count}
              active={activeFilter === t.id}
              onClick={() => setFilterId((cur) => (cur === t.id ? null : t.id))}
            />
          ))}
        </div>
      )}

      <button
        type="button"
        onClick={onCreate}
        className="petal-tap flex items-center justify-center gap-2 text-sm font-bold text-white"
        style={{ minHeight: 44, borderRadius: 'var(--radius-pill)', background: 'var(--color-accent)' }}
        onMouseEnter={(e) => (e.currentTarget.style.background = 'var(--color-accent-hover)')}
        onMouseLeave={(e) => (e.currentTarget.style.background = 'var(--color-accent)')}
      >
        <span className="text-base leading-none">＋</span> New Doc
      </button>

      {docs.length > 1 && (
        <div className="flex items-center justify-end gap-1.5 px-1 text-xs" style={{ color: 'var(--color-muted)' }}>
          <span aria-hidden>↕</span>
          <select
            aria-label="Sort documents"
            value={sort}
            onChange={(e) => setSort(e.target.value as SortMode)}
            className="bg-transparent text-xs font-semibold focus:outline-none"
            style={{ color: 'var(--color-plum)' }}
          >
            {SORTS.map((s) => (
              <option key={s.value} value={s.value}>
                {s.label}
              </option>
            ))}
          </select>
        </div>
      )}

      <div className="flex flex-1 flex-col gap-0.5 overflow-y-auto">
        {filtered.length === 0 ? (
          <p className="px-3 py-6 text-center text-xs" style={{ color: 'var(--color-muted)' }}>
            {activeFilter ? 'No documents with this tag.' : 'No documents yet.'}
          </p>
        ) : (
          filtered.map((doc) => (
            <DocListItem
              key={doc.id}
              doc={doc}
              active={doc.id === selectedId}
              roster={roster}
              onSelect={() => onSelect(doc.id)}
              onDelete={() => onDelete(doc.id)}
              onDuplicate={() => onDuplicate(doc.id)}
              onToggleTag={onToggleTag}
              onCreateTag={onCreateTag}
            />
          ))
        )}
      </div>

      {/* Whole-corpus backup — "download all my writing". Plain download links so
          the browser saves the zip; no extra app state needed. */}
      {docs.length > 0 && (
        <div
          className="flex items-center gap-2 px-1 pt-1 text-xs"
          style={{ color: 'var(--color-muted)', borderTop: '1px solid var(--color-border)' }}
        >
          <span className="font-semibold">备份 · Back up all:</span>
          <a href={api.exportAllUrl('docx')} download className="font-bold hover:underline" style={{ color: 'var(--color-accent-hover)' }}>
            Word
          </a>
          <a href={api.exportAllUrl('md')} download className="font-bold hover:underline" style={{ color: 'var(--color-accent-hover)' }}>
            Markdown
          </a>
        </div>
      )}
    </aside>
  )
}
