'use client'

import {
  Search,
  Plus,
  Trash2,
  ChevronLeft,
  ChevronRight,
  Loader2,
  FileText,
  MoreHorizontal,
} from 'lucide-react'
import { useState, useMemo, useCallback, useEffect, useRef } from 'react'
import { toast } from 'sonner'
import { cmsApi } from '../lib/api.js'
import { useApiData } from '../lib/useApiData.js'
import { editPathForDoc, newPathForCollection } from '../lib/collection-routes.js'

export interface CollectionListProps {
  collectionSlug: string
  config: any
  onNavigate: (path: string) => void
}

type SortField = 'title' | 'status' | 'updatedAt'
type SortOrder = 'asc' | 'desc'

function resolveCollection(config: any, slug: string): any | undefined {
  if (!config?.collections) return undefined
  const list = Array.isArray(config.collections)
    ? config.collections
    : Object.values(config.collections)
  return (list as any[]).find((c: any) => c.slug === slug)
}

function resolveLabel(config: any, slug: string): { singular: string; plural: string } {
  return resolveCollection(config, slug)?.labels ?? { singular: slug, plural: slug }
}

/** One facet dropdown in the filter bar. */
interface FacetDef {
  name: string
  label: string
  /** `options` = fixed list from the config; `values` = in-use values from the field-values API. */
  source: 'options' | 'values'
  options?: Array<{ label: string; value: string }>
}

/** True for array fields shaped like tags: a single required text sub-field. */
function isTagShapedArray(field: any): boolean {
  if (field?.type !== 'array' || !field.fields) return false
  const subs = Object.values(field.fields) as any[]
  return subs.length === 1 && subs[0]?.type === 'text'
}

/**
 * Facetable fields for the filter bar (taxonomy Phase B): structured selects
 * use their config options; free-text `category` and tag-shaped arrays load
 * the collection's in-use values. Capped so the bar stays scannable.
 */
function facetFieldsFor(config: any, slug: string): FacetDef[] {
  const fields = resolveCollection(config, slug)?.fields
  if (!fields || typeof fields !== 'object') return []
  const out: FacetDef[] = []
  for (const [name, field] of Object.entries(fields) as Array<[string, any]>) {
    if (field?.hidden) continue
    if (field?.type === 'select' && Array.isArray(field.options)) {
      out.push({ name, label: field.label ?? name, source: 'options', options: field.options })
    } else if (field?.type === 'text' && name === 'category') {
      out.push({ name, label: field.label ?? 'Category', source: 'values' })
    } else if (isTagShapedArray(field)) {
      out.push({ name, label: field.label ?? name, source: 'values' })
    }
    if (out.length >= 3) break
  }
  return out
}

/** Read a doc's display value for a facet column (select values map to labels). */
function facetCellValue(doc: any, facet: FacetDef): string {
  const raw = doc?.data?.[facet.name]
  if (typeof raw === 'string') {
    if (!raw) return ''
    const opt = facet.options?.find((o) => o.value === raw)
    return opt?.label ?? raw
  }
  if (Array.isArray(raw)) {
    const tags = raw
      .map((item) =>
        typeof item === 'string'
          ? item
          : item && typeof item === 'object'
            ? Object.values(item).find((v) => typeof v === 'string')
            : undefined,
      )
      .filter((v): v is string => Boolean(v))
    if (tags.length === 0) return ''
    return tags.length > 3 ? `${tags.slice(0, 3).join(', ')} +${tags.length - 3}` : tags.join(', ')
  }
  return ''
}

function statusColor(status: string): string {
  switch (status?.toUpperCase()) {
    case 'PUBLISHED':
      return 'var(--actuate-success-bg, #dcfce7)'
    case 'DRAFT':
      return 'var(--actuate-muted-bg, #f3f4f6)'
    case 'ARCHIVED':
      return 'var(--actuate-warning-bg, #fef9c3)'
    case 'SCHEDULED':
      return 'var(--actuate-info-bg, #dbeafe)'
    default:
      return 'var(--actuate-muted-bg, #f3f4f6)'
  }
}

function statusText(status: string): string {
  switch (status?.toUpperCase()) {
    case 'PUBLISHED':
      return 'var(--actuate-success-text, #166534)'
    case 'DRAFT':
      return 'var(--actuate-muted-text, #374151)'
    case 'ARCHIVED':
      return 'var(--actuate-warning-text, #854d0e)'
    case 'SCHEDULED':
      return 'var(--actuate-info-text, #1e40af)'
    default:
      return 'var(--actuate-muted-text, #374151)'
  }
}

function formatDate(d: string | undefined): string {
  if (!d) return '—'
  return new Date(d).toLocaleDateString(undefined, {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
  })
}

export function CollectionList({ collectionSlug, config, onNavigate }: CollectionListProps) {
  const labels = useMemo(() => resolveLabel(config, collectionSlug), [config, collectionSlug])
  const facets = useMemo(() => facetFieldsFor(config, collectionSlug), [config, collectionSlug])
  // Post-type and Pages collections open in dedicated editors — never the
  // generic `/:collection/:id` route (which 404s for a `posts`-slugged post
  // collection and strips section data for any post type).
  const collectionDef = useMemo(
    () => resolveCollection(config, collectionSlug),
    [config, collectionSlug],
  )
  const editPath = useCallback(
    (id: string | number) => editPathForDoc(collectionDef, collectionSlug, String(id)),
    [collectionDef, collectionSlug],
  )
  const newPath = useCallback(
    () => newPathForCollection(collectionDef, collectionSlug),
    [collectionDef, collectionSlug],
  )

  const [page, setPage] = useState(1)
  const [search, setSearch] = useState('')
  const [debouncedSearch, setDebouncedSearch] = useState('')
  const [sort, setSort] = useState<SortField | null>(null)
  const [order, setOrder] = useState<SortOrder>('asc')
  const [selected, setSelected] = useState<Set<string>>(new Set())
  const [filters, setFilters] = useState<Record<string, string>>({})
  // In-use values per `values`-sourced facet, fetched once per collection.
  const [facetValues, setFacetValues] = useState<Record<string, string[]>>({})
  const searchTimer = useRef<ReturnType<typeof setTimeout>>(undefined)

  useEffect(() => {
    clearTimeout(searchTimer.current)
    searchTimer.current = setTimeout(() => {
      setDebouncedSearch(search)
      setPage(1)
    }, 300)
    return () => clearTimeout(searchTimer.current)
  }, [search])

  const endpoint = useMemo(() => {
    let url = `/collections/${collectionSlug}?page=${page}&pageSize=25`
    if (debouncedSearch) url += `&search=${encodeURIComponent(debouncedSearch)}`
    if (sort) url += `&sort=${sort}&order=${order}`
    for (const [field, value] of Object.entries(filters)) {
      if (value) url += `&filter.${encodeURIComponent(field)}=${encodeURIComponent(value)}`
    }
    return url
  }, [collectionSlug, page, debouncedSearch, sort, order, filters])

  const { data, loading, error, refetch } = useApiData<{ docs: any[]; total: number }>(endpoint)
  const docs = data?.docs ?? []
  const total = data?.total ?? 0
  const totalPages = Math.max(1, Math.ceil(total / 25))

  useEffect(() => {
    setPage(1)
    setSelected(new Set())
    setSearch('')
    setFilters({})
    setFacetValues({})
  }, [collectionSlug])

  // Load in-use values for facets that aren't config-defined selects.
  useEffect(() => {
    let cancelled = false
    for (const facet of facets) {
      if (facet.source !== 'values') continue
      cmsApi<{ field: string; values: Array<{ value: string; count: number }> }>(
        `/collections/${collectionSlug}/field-values?field=${encodeURIComponent(facet.name)}`,
      ).then((res) => {
        if (cancelled || !res.data?.values) return
        setFacetValues((prev) => ({
          ...prev,
          [facet.name]: res.data!.values.map((v) => v.value),
        }))
      })
    }
    return () => {
      cancelled = true
    }
  }, [collectionSlug, facets])

  const setFilter = useCallback((field: string, value: string) => {
    setFilters((prev) => {
      const next = { ...prev }
      if (value) next[field] = value
      else delete next[field]
      return next
    })
    setPage(1)
  }, [])

  const toggleSort = useCallback((field: SortField) => {
    setSort((prev) => {
      if (prev === field) {
        setOrder((o) => (o === 'asc' ? 'desc' : 'asc'))
        return field
      }
      setOrder('asc')
      return field
    })
  }, [])

  const toggleSelect = (id: string) =>
    setSelected((prev) => {
      const s = new Set(prev)
      s.has(id) ? s.delete(id) : s.add(id)
      return s
    })

  const toggleAll = (checked: boolean) =>
    setSelected(checked ? new Set(docs.map((d: any) => String(d.id))) : new Set())

  const bulkAction = async (action: 'delete' | 'publish' | 'unpublish') => {
    const ids = [...selected]
    for (const id of ids) {
      if (action === 'delete') {
        await cmsApi(`/collections/${collectionSlug}/${id}`, { method: 'DELETE' })
      } else {
        await cmsApi(`/collections/${collectionSlug}/${id}`, {
          method: 'PUT',
          body: JSON.stringify({ status: action === 'publish' ? 'PUBLISHED' : 'DRAFT' }),
        })
      }
    }
    const verb =
      action === 'delete' ? 'deleted' : action === 'publish' ? 'published' : 'unpublished'
    toast.success(`${ids.length} ${ids.length === 1 ? labels.singular : labels.plural} ${verb}`)
    setSelected(new Set())
    refetch()
  }

  const SortCol = ({ field, children }: { field: SortField; children: string }) => (
    <button
      type="button"
      onClick={() => toggleSort(field)}
      className="flex items-center gap-1 text-xs font-medium transition-opacity hover:opacity-80"
      style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
    >
      {children}
      {sort === field && <span>{order === 'asc' ? '↑' : '↓'}</span>}
    </button>
  )

  if (loading && docs.length === 0) {
    return (
      <div className="flex h-64 items-center justify-center p-4">
        <Loader2
          className="h-6 w-6 animate-spin"
          style={{ color: 'var(--actuate-primary, #2563eb)' }}
        />
      </div>
    )
  }

  return (
    <div className="flex h-full flex-col p-3 pr-6 sm:p-4 sm:pr-8">
      {/* Header */}
      <div className="mb-4 flex flex-wrap items-center justify-between gap-3">
        <div>
          <h1
            className="text-xl font-medium sm:text-2xl"
            style={{ color: 'var(--actuate-text, #111827)' }}
          >
            {labels.plural}
          </h1>
          <p className="text-sm" style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}>
            {total} total
          </p>
        </div>
        <button
          onClick={() => onNavigate(newPath())}
          className="flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors"
          style={{ background: 'var(--actuate-primary, #2563eb)' }}
        >
          <Plus className="h-4 w-4" /> New {labels.singular}
        </button>
      </div>

      {/* Search + facet filters */}
      <div className="mb-4 flex flex-wrap items-center gap-2">
        <div className="relative min-w-[200px] flex-1">
          <Search
            className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2"
            style={{ color: 'var(--actuate-text-muted, #9ca3af)' }}
          />
          <input
            type="text"
            placeholder={`Search ${labels.plural.toLowerCase()}...`}
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="w-full rounded-lg border py-2 pr-3 pl-9 text-sm focus:ring-2 focus:outline-none"
            style={{
              borderColor: 'var(--actuate-border, #d1d5db)',
              color: 'var(--actuate-text, #111827)',
            }}
          />
        </div>
        {facets.map((facet) => {
          const values =
            facet.source === 'options'
              ? (facet.options ?? [])
              : (facetValues[facet.name] ?? []).map((v) => ({ label: v, value: v }))
          if (values.length === 0) return null
          return (
            <select
              key={facet.name}
              aria-label={`Filter by ${facet.label}`}
              value={filters[facet.name] ?? ''}
              onChange={(e) => setFilter(facet.name, e.target.value)}
              className="rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
              style={{
                borderColor: 'var(--actuate-border, #d1d5db)',
                color: filters[facet.name]
                  ? 'var(--actuate-text, #111827)'
                  : 'var(--actuate-text-secondary, #6b7280)',
              }}
            >
              <option value="">All {facet.label.toLowerCase()}</option>
              {values.map((opt) => (
                <option key={opt.value} value={opt.value}>
                  {opt.label}
                </option>
              ))}
            </select>
          )
        })}
        {Object.keys(filters).length > 0 && (
          <button
            type="button"
            onClick={() => setFilters({})}
            className="rounded-lg px-2 py-2 text-sm underline transition-opacity hover:opacity-75"
            style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
          >
            Clear filters
          </button>
        )}
      </div>

      {/* Bulk actions */}
      {selected.size > 0 && (
        <div
          className="mb-4 flex flex-wrap items-center justify-between gap-2 rounded-lg p-3"
          style={{
            background: 'var(--actuate-info-bg, #eff6ff)',
            borderColor: 'var(--actuate-info-border, #bfdbfe)',
            borderWidth: 1,
            borderStyle: 'solid',
          }}
        >
          <span className="text-sm" style={{ color: 'var(--actuate-info-text, #1e40af)' }}>
            {selected.size} selected
          </span>
          <div className="flex gap-2">
            <button
              onClick={() => bulkAction('publish')}
              className="rounded-lg px-3 py-1.5 text-sm text-white"
              style={{ background: 'var(--actuate-success, #16a34a)' }}
            >
              Publish
            </button>
            <button
              onClick={() => bulkAction('unpublish')}
              className="rounded-lg px-3 py-1.5 text-sm text-white"
              style={{ background: 'var(--actuate-warning, #ca8a04)' }}
            >
              Unpublish
            </button>
            <button
              onClick={() => bulkAction('delete')}
              className="rounded-lg px-3 py-1.5 text-sm text-white"
              style={{ background: 'var(--actuate-danger, #dc2626)' }}
            >
              <Trash2 className="-mt-0.5 mr-1 inline h-3.5 w-3.5" />
              Delete
            </button>
          </div>
        </div>
      )}

      {error && (
        <div
          className="mb-4 rounded-lg p-3 text-sm"
          style={{
            background: 'var(--actuate-danger-bg, #fef2f2)',
            color: 'var(--actuate-danger-text, #991b1b)',
          }}
        >
          {error} —{' '}
          <button onClick={refetch} className="underline">
            retry
          </button>
        </div>
      )}

      {/* Table */}
      {docs.length === 0 && !loading ? (
        <div
          className="flex flex-1 flex-col items-center justify-center rounded-lg border p-8"
          style={{
            borderColor: 'var(--actuate-border, #d1d5db)',
            color: 'var(--actuate-text-secondary, #6b7280)',
          }}
        >
          <FileText className="mb-3 h-10 w-10 opacity-40" />
          <p className="mb-3 text-sm">No {labels.plural.toLowerCase()} found</p>
          <button
            onClick={() => onNavigate(newPath())}
            className="rounded-lg px-4 py-2 text-sm text-white"
            style={{ background: 'var(--actuate-primary, #2563eb)' }}
          >
            Create {labels.singular}
          </button>
        </div>
      ) : (
        <div
          className="flex-1 overflow-auto rounded-lg border"
          style={{ borderColor: 'var(--actuate-border, #d1d5db)' }}
        >
          <table className="w-full text-sm">
            <thead
              className="sticky top-0"
              style={{
                background: 'var(--actuate-surface-alt, #f9fafb)',
                borderBottom: '1px solid var(--actuate-border, #d1d5db)',
              }}
            >
              <tr>
                <th className="w-10 px-3 py-2 text-left">
                  <input
                    type="checkbox"
                    checked={selected.size === docs.length && docs.length > 0}
                    onChange={(e) => toggleAll(e.target.checked)}
                    className="rounded"
                  />
                </th>
                <th className="px-3 py-2 text-left">
                  <SortCol field="title">Title</SortCol>
                </th>
                {facets.map((facet) => (
                  <th
                    key={facet.name}
                    className="px-3 py-2 text-left text-xs font-medium"
                    style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
                  >
                    {facet.label}
                  </th>
                ))}
                <th className="px-3 py-2 text-left">
                  <SortCol field="status">Status</SortCol>
                </th>
                <th className="px-3 py-2 text-left">
                  <SortCol field="updatedAt">Updated</SortCol>
                </th>
                <th
                  className="px-3 py-2 text-left text-xs font-medium"
                  style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
                >
                  Actions
                </th>
              </tr>
            </thead>
            <tbody>
              {docs.map((doc: any) => (
                <tr
                  key={doc.id}
                  className="transition-colors hover:opacity-95"
                  style={{ borderBottom: '1px solid var(--actuate-border, #e5e7eb)' }}
                >
                  <td className="px-3 py-2">
                    <input
                      type="checkbox"
                      checked={selected.has(String(doc.id))}
                      onChange={() => toggleSelect(String(doc.id))}
                      className="rounded"
                    />
                  </td>
                  <td className="px-3 py-2">
                    <button
                      type="button"
                      onClick={() => onNavigate(editPath(doc.id))}
                      className="text-left font-medium hover:underline"
                      style={{ color: 'var(--actuate-text, #111827)' }}
                    >
                      {doc.title || doc.name || `#${doc.id}`}
                    </button>
                  </td>
                  {facets.map((facet) => (
                    <td
                      key={facet.name}
                      className="max-w-[200px] truncate px-3 py-2"
                      style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
                      title={facetCellValue(doc, facet) || undefined}
                    >
                      {facetCellValue(doc, facet) || '—'}
                    </td>
                  ))}
                  <td className="px-3 py-2">
                    <span
                      className="inline-block rounded-full px-2 py-0.5 text-xs font-medium"
                      style={{ background: statusColor(doc.status), color: statusText(doc.status) }}
                    >
                      {doc.status ?? 'DRAFT'}
                    </span>
                  </td>
                  <td
                    className="px-3 py-2"
                    style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
                  >
                    {formatDate(doc.updatedAt)}
                  </td>
                  <td className="px-3 py-2">
                    <button
                      type="button"
                      onClick={() => onNavigate(editPath(doc.id))}
                      className="rounded p-1.5 transition-opacity hover:opacity-75"
                      title="Edit"
                    >
                      <MoreHorizontal
                        className="h-4 w-4"
                        style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
                      />
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Pagination */}
      {totalPages > 1 && (
        <div
          className="mt-4 flex items-center justify-between text-sm"
          style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
        >
          <span>
            Page {page} of {totalPages}
          </span>
          <div className="flex gap-2">
            <button
              disabled={page <= 1}
              onClick={() => setPage((p) => p - 1)}
              className="flex items-center gap-1 rounded-lg border px-3 py-1.5 transition-opacity disabled:opacity-40"
              style={{ borderColor: 'var(--actuate-border, #d1d5db)' }}
            >
              <ChevronLeft className="h-4 w-4" /> Previous
            </button>
            <button
              disabled={page >= totalPages}
              onClick={() => setPage((p) => p + 1)}
              className="flex items-center gap-1 rounded-lg border px-3 py-1.5 transition-opacity disabled:opacity-40"
              style={{ borderColor: 'var(--actuate-border, #d1d5db)' }}
            >
              Next <ChevronRight className="h-4 w-4" />
            </button>
          </div>
        </div>
      )}
    </div>
  )
}
