import { useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { FaDownload } from 'react-icons/fa'
import { api, createSSE, endpoints } from '../../api'
import { getClassColor, getClassNameFallback, hexToRgba } from '../../class-colors'
import type { Media, AnnotationListItem, PaginatedResponse } from '../../types'

interface Props {
  media: Media | null
  annotations: AnnotationListItem[]
  selectedAnnotation: AnnotationListItem | null
  onSelect: (ann: AnnotationListItem) => void
  onAnnotationsUpdate: (anns: AnnotationListItem[]) => void
  onDownload?: (ann: AnnotationListItem) => void
}

function getRowGradient(ann: AnnotationListItem): string {
  if (ann.detections.length === 0) {
    return 'linear-gradient(90deg, rgba(221,221,221,0.10), rgba(221,221,221,0.04))'
  }
  if (ann.detections.length === 1) {
    const c = getClassColor(ann.detections[0].classNum)
    return `linear-gradient(90deg, ${hexToRgba(c, 0.55)} 0%, ${hexToRgba(c, 0.10)} 60%, transparent 100%)`
  }
  const n = ann.detections.length
  const bandWidth = 100 / n
  const stops: string[] = []
  ann.detections.forEach((d, i) => {
    const c = getClassColor(d.classNum)
    const start = i * bandWidth
    const mid = start + bandWidth * 0.6
    const end = (i + 1) * bandWidth
    stops.push(`${hexToRgba(c, 0.50)} ${start}%`)
    stops.push(`${hexToRgba(c, 0.10)} ${mid}%`)
    if (i < n - 1) stops.push(`${hexToRgba(c, 0.10)} ${end - 0.01}%`)
  })
  return `linear-gradient(90deg, ${stops.join(', ')})`
}

interface ClassAgg { classNum: number; color: string; count: number }

function aggregateClasses(annotations: AnnotationListItem[]): ClassAgg[] {
  const counts = new Map<number, number>()
  for (const ann of annotations) {
    for (const d of ann.detections) {
      counts.set(d.classNum, (counts.get(d.classNum) ?? 0) + 1)
    }
  }
  return [...counts.entries()]
    .map(([classNum, count]) => ({ classNum, color: getClassColor(classNum), count }))
    .sort((a, b) => b.count - a.count)
    .slice(0, 6)
}

export default function AnnotationsSidebar({ media, annotations, selectedAnnotation, onSelect, onAnnotationsUpdate, onDownload }: Props) {
  const { t } = useTranslation()

  useEffect(() => {
    if (!media) return
    return createSSE<{ annotationId: string; mediaId: string; status: number }>(endpoints.annotations.annotationEvents(), (event) => {
      if (event.mediaId === media.id) {
        api.get<PaginatedResponse<AnnotationListItem>>(
          endpoints.annotations.annotationsByMedia(media.id),
        ).then(res => onAnnotationsUpdate(res.items)).catch(() => {})
      }
    })
  }, [media, onAnnotationsUpdate])

  const totals = useMemo(() => ({
    total: annotations.length,
    empty: annotations.filter(a => a.detections.length === 0).length,
  }), [annotations])

  const classDist = useMemo(() => aggregateClasses(annotations), [annotations])

  return (
    <div className="flex flex-col h-full bg-surface-1">
      <div className="flex items-center justify-between px-3 h-9 border-b border-border-hair">
        <div className="flex items-center gap-2">
          <span className="sect-head">{t('annotations.title')}</span>
          <span className="mono text-[10px] text-text-muted">{String(annotations.length).padStart(2, '0')}</span>
        </div>
        <div className="flex items-center gap-1">
          <button className="ibtn" style={{ width: 22, height: 22 }} title={t('annotations.filter')}>
            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polygon points="22 3 2 3 10 12.5 10 19 14 21 14 12.5"/></svg>
          </button>
          <button className="ibtn" style={{ width: 22, height: 22 }} title={t('annotations.sort')}>
            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 6h13M3 12h9M3 18h5M17 8l4-4 4 4M21 4v16"/></svg>
          </button>
        </div>
      </div>

      <div className="grid grid-cols-[44px_1fr_auto] gap-2 px-3 h-6 items-center border-b border-border-hair">
        <span className="micro">{t('annotations.colTime')}</span>
        <span className="micro">{t('annotations.colClass')}</span>
        <span className="micro">{t('annotations.colConf')}</span>
      </div>

      <div className="flex-1 overflow-y-auto min-h-0">
        {annotations.map(ann => {
          const isSelected = selectedAnnotation?.id === ann.id
          const isEmpty = ann.detections.length === 0
          const first = ann.detections[0]
          const extra = ann.detections.length > 1 ? ` +${ann.detections.length - 1}` : ''
          const maxConf = ann.detections.reduce((m, d) => Math.max(m, d.confidence ?? 0), 0)
          const className = first ? (first.label || getClassNameFallback(first.classNum)) : ''
          return (
            <div
              key={ann.id}
              onClick={() => onSelect(ann)}
              className={`ann-row${isSelected ? ' active' : ''}`}
              style={{ ['--row-grad' as string]: getRowGradient(ann) }}
            >
              <span className={`mono text-[11px] ${isSelected ? 'text-accent-amber font-semibold' : isEmpty ? 'text-text-muted' : 'text-text-secondary'}`}>
                {ann.time || '—'}
              </span>
              {isEmpty
                ? <span className="text-text-muted italic">{t('annotations.emptyFrame')}</span>
                : <span className={`truncate ${isSelected ? 'text-text-primary font-semibold' : 'text-text-primary'}`}>{className}{extra}</span>
              }
              <div className="flex items-center gap-1.5">
                {isSelected && !isEmpty && onDownload && (
                  <button
                    onClick={e => { e.stopPropagation(); onDownload(ann) }}
                    className="ibtn"
                    style={{ width: 18, height: 18 }}
                    title="Download annotation"
                  >
                    <FaDownload size={9} />
                  </button>
                )}
                <span className={`mono text-[10px] ${isEmpty ? 'text-text-muted' : isSelected ? 'text-accent-amber' : 'text-text-secondary'}`}>
                  {isEmpty ? '—' : `${Math.round(maxConf * 100)}%`}
                </span>
              </div>
            </div>
          )
        })}
        {annotations.length === 0 && (
          <div className="p-3 text-text-muted text-xs text-center">{t('common.noData')}</div>
        )}
      </div>

      <div className="border-t border-border-hair px-3 py-2.5 bg-surface-0">
        <div className="flex items-center justify-between mb-2">
          <span className="micro">{t('annotations.summary')}</span>
          <span className="mono text-[10px] text-text-muted">
            {t('annotations.annCount', { count: totals.total })} · {t('annotations.emptyCount', { count: totals.empty })}
          </span>
        </div>
        {classDist.length > 0 && (
          <>
            <div className="flex items-center gap-1 h-2">
              {classDist.map(c => (
                <span key={c.classNum} style={{ flex: c.count, background: c.color, height: '100%' }} />
              ))}
            </div>
            <div className="flex items-center justify-between mt-2 mono text-[10px] text-text-muted">
              {classDist.map(c => (
                <span key={c.classNum} className="flex items-center gap-1">
                  <span style={{ color: c.color }}>■</span> {c.count}
                </span>
              ))}
            </div>
          </>
        )}
      </div>
    </div>
  )
}
