'use client'

import { useState, useEffect, useRef, useCallback } from 'react'
import { Search, X, Loader2, Plus } from 'lucide-react'
import { cmsApi } from '../lib/api.js'

export interface RelationshipFieldProps {
  label: string
  value?: string | string[]
  onChange: (value: string | string[]) => void
  multi?: boolean
  required?: boolean
  helpText?: string
  relationTo?: string
  useAsTitle?: string
  onNavigate?: (path: string) => void
}

interface RelatedDoc {
  id: string
  title?: string
  status?: string
  collection?: string
  updatedAt?: string
  data?: Record<string, any>
}

const STATUS_STYLES: Record<string, string> = {
  PUBLISHED: 'bg-green-100 text-green-800',
  DRAFT: 'bg-yellow-100 text-yellow-800',
  ARCHIVED: 'bg-gray-100 text-gray-600',
  SCHEDULED: 'bg-blue-100 text-blue-800',
}

function relativeTime(dateStr: string | undefined): string {
  if (!dateStr) return ''
  const diff = Date.now() - new Date(dateStr).getTime()
  const seconds = Math.floor(diff / 1000)
  if (seconds < 60) return 'just now'
  const minutes = Math.floor(seconds / 60)
  if (minutes < 60) return `${minutes}m ago`
  const hours = Math.floor(minutes / 60)
  if (hours < 24) return `${hours}h ago`
  const days = Math.floor(hours / 24)
  if (days < 30) return `${days}d ago`
  const months = Math.floor(days / 30)
  if (months < 12) return `${months}mo ago`
  return `${Math.floor(months / 12)}y ago`
}

export function RelationshipField({
  label,
  value,
  onChange,
  multi = false,
  required,
  helpText,
  relationTo = 'pages',
  useAsTitle = 'title',
  onNavigate,
}: RelationshipFieldProps) {
  const [searchTerm, setSearchTerm] = useState('')
  const [open, setOpen] = useState(false)
  const [options, setOptions] = useState<RelatedDoc[]>([])
  const [loading, setLoading] = useState(false)
  const dropdownRef = useRef<HTMLDivElement>(null)
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  const selectedIds = multi
    ? Array.isArray(value)
      ? value
      : []
    : typeof value === 'string' && value
      ? [value]
      : []

  const fetchOptions = useCallback(
    async (query: string) => {
      setLoading(true)
      const searchParam = query ? `&search=${encodeURIComponent(query)}` : ''
      const res = await cmsApi<{ docs: RelatedDoc[] }>(
        `/collections/${relationTo}?pageSize=50${searchParam}`,
      )
      if (res.data) {
        const docs: RelatedDoc[] = (res.data as any).docs ?? []
        setOptions(docs)
      }
      setLoading(false)
    },
    [relationTo],
  )

  useEffect(() => {
    if (open) fetchOptions(searchTerm)
  }, [open])

  const handleSearch = useCallback(
    (query: string) => {
      setSearchTerm(query)
      if (debounceRef.current) clearTimeout(debounceRef.current)
      debounceRef.current = setTimeout(() => fetchOptions(query), 300)
    },
    [fetchOptions],
  )

  useEffect(() => {
    function handleClickOutside(e: MouseEvent) {
      if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
        setOpen(false)
      }
    }
    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [])

  function getDocTitle(doc: RelatedDoc): string {
    if (doc.title) return doc.title
    const d = doc.data
    if (d && typeof d === 'object') {
      if (typeof d[useAsTitle] === 'string') return d[useAsTitle]
      if (typeof d.title === 'string') return d.title
      if (typeof d.name === 'string') return d.name
    }
    return doc.id
  }

  function handleToggle(id: string) {
    if (multi) {
      const next = selectedIds.includes(id)
        ? selectedIds.filter((v) => v !== id)
        : [...selectedIds, id]
      onChange(next)
    } else {
      onChange(id)
      setOpen(false)
    }
  }

  function handleRemove(id: string) {
    if (multi) {
      onChange(selectedIds.filter((v) => v !== id))
    } else {
      onChange('')
    }
  }

  const selectedItems = options.filter((opt) => selectedIds.includes(opt.id))
  const unselectedItems = options.filter((opt) => !selectedIds.includes(opt.id))

  function renderOption(opt: RelatedDoc, isSelected: boolean) {
    const status = opt.status ?? (opt.data as any)?.status
    const collection = opt.collection ?? relationTo
    const statusClass = STATUS_STYLES[status] ?? 'bg-gray-100 text-gray-600'

    return (
      <button
        type="button"
        onClick={() => handleToggle(opt.id)}
        className={`flex w-full items-center gap-2 px-3 py-2 text-sm hover:bg-[var(--accent)] ${isSelected ? 'font-medium' : ''}`}
      >
        <div className="min-w-0 flex-1 text-left">
          <div className="flex items-center gap-2">
            <span className="truncate">{getDocTitle(opt)}</span>
            {isSelected && <span className="shrink-0 text-[var(--primary)]">&#10003;</span>}
          </div>
          <div className="mt-0.5 flex items-center gap-2">
            <span className="text-[10px] text-[var(--muted-foreground)]">{collection}</span>
            {opt.updatedAt && (
              <span className="text-[10px] text-[var(--muted-foreground)]">
                {relativeTime(opt.updatedAt)}
              </span>
            )}
          </div>
        </div>
        {status && (
          <span className={`shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium ${statusClass}`}>
            {status}
          </span>
        )}
      </button>
    )
  }

  return (
    <div className="relative" ref={dropdownRef}>
      <label className="mb-1 block text-sm font-medium">
        {label}
        {required && <span className="ml-0.5 text-[var(--destructive)]">*</span>}
      </label>

      {selectedItems.length > 0 && (
        <div className="mb-2 flex flex-wrap gap-1">
          {selectedItems.map((item) => (
            <span
              key={item.id}
              className="inline-flex items-center gap-1 rounded-md bg-[var(--accent)] px-2 py-1 text-xs"
            >
              {getDocTitle(item)}
              <button
                type="button"
                onClick={() => handleRemove(item.id)}
                className="hover:text-[var(--destructive)]"
              >
                <X className="h-3 w-3" />
              </button>
            </span>
          ))}
        </div>
      )}

      <div className="relative">
        <Search className="pointer-events-none absolute top-1/2 left-2.5 h-4 w-4 -translate-y-1/2 text-[var(--muted-foreground)]" />
        <input
          type="text"
          value={searchTerm}
          onChange={(e) => handleSearch(e.target.value)}
          onFocus={() => setOpen(true)}
          placeholder={`Search ${relationTo}...`}
          className="w-full rounded-md border border-[var(--border)] bg-[var(--input-background)] py-2 pr-3 pl-8 text-sm outline-none focus:ring-2 focus:ring-[var(--ring)]"
        />
        {loading && (
          <Loader2 className="absolute top-1/2 right-2.5 h-4 w-4 -translate-y-1/2 animate-spin text-[var(--muted-foreground)]" />
        )}

        {open && (
          <ul className="absolute z-50 mt-1 max-h-60 w-full overflow-y-auto rounded-md border border-[var(--border)] bg-[var(--popover)] py-1 shadow-lg">
            {unselectedItems.map((opt) => (
              <li key={opt.id}>{renderOption(opt, false)}</li>
            ))}
            {selectedItems.length > 0 && unselectedItems.length > 0 && (
              <li className="my-1 border-t border-[var(--border)]" />
            )}
            {selectedItems.map((opt) => (
              <li key={opt.id}>{renderOption(opt, true)}</li>
            ))}
            {options.length === 0 && !loading && (
              <li className="px-3 py-2 text-sm text-[var(--muted-foreground)]">No results</li>
            )}
            <li className="mt-1 border-t border-[var(--border)]">
              <button
                type="button"
                onClick={() => {
                  setOpen(false)
                  onNavigate?.(`/${relationTo}/new`)
                }}
                className="flex w-full items-center gap-2 px-3 py-2 text-sm text-[var(--primary)] hover:bg-[var(--accent)]"
              >
                <Plus className="h-3.5 w-3.5" />
                Create New
              </button>
            </li>
          </ul>
        )}
      </div>

      {helpText && <p className="mt-1 text-xs text-[var(--muted-foreground)]">{helpText}</p>}
    </div>
  )
}
