import { useState, useMemo, useCallback } from 'react'
import { Palette, ArrowLeft, Loader2 } from 'lucide-react'
import clsx from 'clsx'
import { Button } from '@/components/ui/button'
import { photos as photosApi } from '../../services/api'
import { useFilterStore } from '../../store/filterStore'
import { usePhotosQuery } from '../../hooks/usePhotosQuery'
import { COLOR_LABEL_OPTIONS, type ColorLabel } from '../../constants/colorLabels'
import { useCardGridNav } from '../../hooks/useCardGridNav'
import { Timeline } from '../timeline/Timeline'
import type { Photo } from '../../types/photo'

interface ColorGroup {
  label: string
  value: ColorLabel | null
  className: string
  count: number
  representative: Photo | null
}

/**
 * Colors view — two states:
 * 1. Grid of color label cards (default) — arrow keys + Enter to browse
 * 2. Detail view showing a color's photos in the full Timeline — Esc to go back
 */
export function ColorsView() {
  const { data: allPhotos = [], isLoading } = usePhotosQuery()
  const setColorLabel = useFilterStore((s) => s.setColorLabel)
  const [selectedGroup, setSelectedGroup] = useState<ColorGroup | null>(null)

  const groups = useMemo(() => {
    const buckets = new Map<string, Photo[]>()
    const uncolored: Photo[] = []

    for (const photo of allPhotos) {
      if (photo.color_label) {
        const arr = buckets.get(photo.color_label) ?? []
        arr.push(photo)
        buckets.set(photo.color_label, arr)
      } else {
        uncolored.push(photo)
      }
    }

    const result: ColorGroup[] = []
    for (const { value, className } of COLOR_LABEL_OPTIONS) {
      const photos = buckets.get(value) ?? []
      if (photos.length === 0) continue
      result.push({
        label: value.charAt(0).toUpperCase() + value.slice(1),
        value,
        className,
        count: photos.length,
        representative: photos[0],
      })
    }
    if (uncolored.length > 0) {
      result.push({
        label: 'Uncolored',
        value: null,
        className: 'bg-neutral-400',
        count: uncolored.length,
        representative: uncolored[0],
      })
    }
    result.sort((a, b) => b.count - a.count)
    return result
  }, [allPhotos])

  const enterDetail = useCallback(
    (group: ColorGroup) => {
      setColorLabel((group.value ?? 'none') as ColorLabel)
      setSelectedGroup(group)
    },
    [setColorLabel]
  )

  const exitDetail = useCallback(() => {
    setColorLabel(null)
    setSelectedGroup(null)
  }, [setColorLabel])

  const { activeIndex, gridRef } = useCardGridNav({
    items: groups,
    inDetail: selectedGroup !== null,
    onEnter: enterDetail,
    onExit: exitDetail,
  })

  if (selectedGroup) {
    return (
      <div className="flex h-full flex-col overflow-hidden">
        <div className="flex items-center gap-3 border-b border-border px-4 py-3">
          <Button
            variant="ghost"
            size="icon"
            className="h-7 w-7 text-text-muted"
            onClick={exitDetail}
            title="Back to colors"
          >
            <ArrowLeft className="h-4 w-4" />
          </Button>
          <div className="flex items-center gap-2">
            <span className={`inline-block h-3 w-3 rounded-full ${selectedGroup.className}`} />
            <h2 className="text-sm font-semibold text-text">{selectedGroup.label}</h2>
          </div>
        </div>
        <div className="flex-1 overflow-hidden">
          <Timeline />
        </div>
      </div>
    )
  }

  if (isLoading) {
    return (
      <div className="flex h-full items-center justify-center text-text-muted">
        <Loader2 className="mr-2 h-5 w-5 animate-spin" />
        Loading colors...
      </div>
    )
  }

  if (groups.length === 0) {
    return (
      <div className="flex h-full flex-col items-center justify-center gap-3 text-text-muted">
        <Palette className="h-12 w-12 opacity-40" />
        <p className="text-sm">No color labels assigned yet</p>
        <p className="max-w-xs text-center text-xs opacity-70">
          Color labels will appear here once you assign them to photos.
        </p>
      </div>
    )
  }

  return (
    <div className="h-full overflow-auto p-4 pb-20">
      <div className="mb-4 flex items-center gap-2 text-text-muted">
        <Palette className="h-4 w-4" />
        <span className="text-sm font-medium">
          {groups.length} {groups.length === 1 ? 'color' : 'colors'}
        </span>
      </div>

      <div
        ref={gridRef}
        className="grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-3"
      >
        {groups.map((group, i) => (
          <div
            key={group.label}
            className={clsx(
              'group cursor-pointer overflow-hidden rounded-lg border bg-surface transition-all hover:border-primary/50 hover:shadow-md',
              i === activeIndex
                ? 'border-primary ring-1 ring-primary/30'
                : 'border-border'
            )}
            onClick={() => enterDetail(group)}
          >
            <div className="relative aspect-square overflow-hidden bg-surface-2">
              {group.representative ? (
                <img
                  src={photosApi.getThumbnailUrl(group.representative.id, 'small')}
                  alt={group.label}
                  className="h-full w-full object-cover"
                />
              ) : (
                <div className="flex h-full w-full items-center justify-center">
                  <Palette className="h-10 w-10 text-text-muted/30" />
                </div>
              )}

              <span className="absolute bottom-1.5 right-1.5 rounded-full bg-black/60 px-2 py-0.5 text-[11px] font-medium text-white backdrop-blur-sm">
                {group.count}
              </span>
            </div>

            <div className="flex items-center gap-1.5 px-2 py-1.5">
              <span className={`inline-block h-2.5 w-2.5 rounded-full ${group.className}`} />
              <p className="truncate text-xs font-medium text-text">{group.label}</p>
            </div>
          </div>
        ))}
      </div>
    </div>
  )
}
