import { useState, useEffect, useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { FaPen } from 'react-icons/fa'
import { api, endpoints } from '../../api'
import { useDebounce, useResizablePanel } from '../../hooks'
import { useFlight, DetectionClasses } from '../../components'
import { useSavedAnnotations } from '../../components/SavedAnnotationsContext'
import CanvasEditor from '../annotations/CanvasEditor'
import { recaptureThumbnails } from '../annotations/thumbnail'
import type { SavedDetection } from '../../components/SavedAnnotationsContext'
import type { DatasetItem, PaginatedResponse, ClassDistributionItem, AnnotationListItem, Detection, Media } from '../../types'
import { AnnotationSource, AnnotationStatus } from '../../types'

interface DatasetCard {
  annotationId: string
  imageName: string
  status: AnnotationStatus
  createdDate: string
  thumbnailUrl: string
  isSeed: boolean
  isLocal: boolean
  detections?: Detection[]
  mediaId?: string
  time?: string | null
  fullFrame?: string
  annotationLocalId?: string
}

type Tab = 'annotations' | 'editor' | 'distribution'

export default function DatasetPage() {
  const { t } = useTranslation()
  const { selectedFlight } = useFlight()
  const { saved: savedAnnotations, removeSaved, replaceGroup, updateStatus } = useSavedAnnotations()
  const leftPanel = useResizablePanel(250, 200, 400)

  const [items, setItems] = useState<DatasetItem[]>([])
  const [totalCount, setTotalCount] = useState(0)
  const [page, setPage] = useState(1)
  const [pageSize] = useState(20)
  const [fromDate, setFromDate] = useState('')
  const [toDate, setToDate] = useState('')
  const [statusFilter, setStatusFilter] = useState<AnnotationStatus | null>(null)
  const [objectsOnly, setObjectsOnly] = useState(false)
  const [search, setSearch] = useState('')
  const debouncedSearch = useDebounce(search, 400)
  const [selectedClassNum, setSelectedClassNum] = useState(0)
  const [photoMode, setPhotoMode] = useState(0)
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
  const [tab, setTab] = useState<Tab>('annotations')
  const [editorAnnotation, setEditorAnnotation] = useState<AnnotationListItem | null>(null)
  const [editorDetections, setEditorDetections] = useState<Detection[]>([])
  const [distribution, setDistribution] = useState<ClassDistributionItem[]>([])

  const fetchItems = useCallback(async () => {
    const params = new URLSearchParams({ page: String(page), pageSize: String(pageSize) })
    if (fromDate) params.set('fromDate', fromDate)
    if (toDate) params.set('toDate', toDate)
    if (selectedFlight) params.set('flightId', selectedFlight.id)
    if (statusFilter !== null) params.set('status', String(statusFilter))
    if (selectedClassNum) params.set('classNum', String(selectedClassNum))
    if (objectsOnly) params.set('hasDetections', 'true')
    if (debouncedSearch) params.set('name', debouncedSearch)
    try {
      const res = await api.get<PaginatedResponse<DatasetItem>>(endpoints.annotations.dataset(params.toString()))
      setItems(res.items)
      setTotalCount(res.totalCount)
    } catch {}
  }, [page, pageSize, fromDate, toDate, selectedFlight, statusFilter, selectedClassNum, objectsOnly, debouncedSearch])

  useEffect(() => { fetchItems() }, [fetchItems])

  const cards = useMemo<DatasetCard[]>(() => {
    const localCards: DatasetCard[] = savedAnnotations
      .filter(sd => {
        if (selectedFlight && sd.flightId && sd.flightId !== selectedFlight.id) return false
        if (statusFilter !== null && sd.status !== statusFilter) return false
        if (selectedClassNum && sd.detection.classNum !== selectedClassNum) return false
        if (debouncedSearch && !sd.mediaName.toLowerCase().includes(debouncedSearch.toLowerCase())) return false
        if (fromDate && sd.createdDate < fromDate) return false
        if (toDate && sd.createdDate > `${toDate}T23:59:59`) return false
        return true
      })
      .map(sd => ({
        annotationId: sd.id,
        imageName: sd.mediaName,
        status: sd.status,
        createdDate: sd.createdDate,
        thumbnailUrl: sd.thumbnail,
        isSeed: false,
        isLocal: true,
        detections: [sd.detection],
        mediaId: sd.mediaId,
        time: sd.time,
        fullFrame: sd.fullFrame,
        annotationLocalId: sd.annotationLocalId,
      }))

    const remoteCards: DatasetCard[] = items.map(item => ({
      annotationId: item.annotationId,
      imageName: item.imageName,
      status: item.status,
      createdDate: item.createdDate,
      thumbnailUrl: endpoints.annotations.annotationThumbnail(item.annotationId),
      isSeed: item.isSeed,
      isLocal: false,
    }))

    return [...localCards, ...remoteCards]
  }, [savedAnnotations, items, selectedFlight, statusFilter, objectsOnly, selectedClassNum, debouncedSearch, fromDate, toDate])

  const [editorFullFrame, setEditorFullFrame] = useState<string>('')
  const [editorLocalGroupId, setEditorLocalGroupId] = useState<string | null>(null)
  const [editorSaving, setEditorSaving] = useState(false)

  const handleDoubleClick = async (card: DatasetCard) => {
    if (card.isLocal && card.detections && card.mediaId) {
      setEditorAnnotation({
        id: card.annotationId,
        mediaId: card.mediaId,
        time: card.time ?? null,
        createdDate: card.createdDate,
        userId: 'local',
        source: AnnotationSource.Manual,
        status: card.status,
        isSplit: false,
        splitTile: null,
        detections: card.detections,
      })
      setEditorDetections(card.detections)
      setEditorFullFrame(card.fullFrame ?? '')
      setEditorLocalGroupId(card.annotationLocalId ?? null)
      setTab('editor')
      return
    }
    setEditorFullFrame('')
    setEditorLocalGroupId(null)
    try {
      const ann = await api.get<AnnotationListItem>(endpoints.annotations.datasetItem(card.annotationId))
      setEditorAnnotation(ann)
      setEditorDetections(ann.detections)
      setTab('editor')
    } catch {}
  }

  const handleEditorSave = async () => {
    if (!editorAnnotation) return
    setEditorSaving(true)
    try {
      if (editorLocalGroupId) {
        const existing = savedAnnotations.find(s => s.annotationLocalId === editorLocalGroupId)
        const thumbs = await recaptureThumbnails(editorFullFrame, editorDetections)
        const now = new Date().toISOString()
        const items: SavedDetection[] = editorDetections.map((d, i) => ({
          id: `${editorLocalGroupId}:${d.id ?? i}`,
          annotationLocalId: editorLocalGroupId,
          mediaId: editorAnnotation.mediaId,
          mediaName: existing?.mediaName ?? '',
          thumbnail: thumbs[i] ?? '',
          fullFrame: editorFullFrame,
          status: AnnotationStatus.Edited,
          source: existing?.source ?? AnnotationSource.Manual,
          createdDate: existing?.createdDate ?? now,
          detection: d,
          time: editorAnnotation.time,
          flightId: existing?.flightId ?? null,
        }))
        replaceGroup(editorLocalGroupId, items)
      }
      setTab('annotations')
    } finally {
      setEditorSaving(false)
    }
  }

  const handleEditorCancel = () => {
    if (editorAnnotation) setEditorDetections(editorAnnotation.detections)
    setTab('annotations')
  }

  const handleValidate = async () => {
    if (selectedIds.size === 0) return
    const allIds = Array.from(selectedIds)
    const localIds = allIds.filter(id => id.startsWith('saved-') || id.startsWith('local-'))
    const backendIds = allIds.filter(id => !id.startsWith('saved-') && !id.startsWith('local-'))

    if (backendIds.length > 0) {
      try {
        await api.post(endpoints.annotations.datasetBulkStatus(), {
          annotationIds: backendIds,
          status: AnnotationStatus.Validated,
        })
      } catch {}
    }
    if (localIds.length > 0) {
      updateStatus(localIds, AnnotationStatus.Validated)
    }
    setSelectedIds(new Set())
    fetchItems()
  }

  const loadDistribution = useCallback(async () => {
    try {
      const data = await api.get<ClassDistributionItem[]>(endpoints.annotations.datasetClassDistribution())
      setDistribution(data)
    } catch {}
  }, [])

  useEffect(() => { if (tab === 'distribution') loadDistribution() }, [tab, loadDistribution])

  const maxDistCount = Math.max(...distribution.map(d => d.count), 1)
  const totalPages = Math.ceil(totalCount / pageSize)

  const editorMedia: Media | null = editorAnnotation ? {
    id: editorAnnotation.mediaId, name: '', path: editorFullFrame, mediaType: 1, mediaStatus: 0,
    duration: null, annotationCount: 0, waypointId: null, userId: '',
  } : null

  const statusButtons = [
    { label: 'All', value: null },
    { label: t('dataset.status.created'), value: AnnotationStatus.Created },
    { label: t('dataset.status.edited'), value: AnnotationStatus.Edited },
    { label: t('dataset.status.validated'), value: AnnotationStatus.Validated },
  ]

  return (
    <div className="flex h-full">
      {/* Left panel */}
      <div style={{ width: leftPanel.width }} className="bg-az-panel border-r border-az-border flex flex-col shrink-0">
        <DetectionClasses
          selectedClassNum={selectedClassNum}
          onSelect={setSelectedClassNum}
          photoMode={photoMode}
          onPhotoModeChange={setPhotoMode}
        />
        <div className="p-2 border-t border-az-border">
          <label className="flex items-center gap-1.5 text-xs text-az-text cursor-pointer">
            <input type="checkbox" checked={objectsOnly} onChange={e => setObjectsOnly(e.target.checked)} className="accent-az-orange" />
            {t('dataset.objectsOnly')}
          </label>
        </div>
        <div className="p-2 border-t border-az-border">
          <input
            value={search}
            onChange={e => setSearch(e.target.value)}
            placeholder={t('dataset.search')}
            className="w-full bg-az-bg border border-az-border rounded px-2 py-1 text-xs text-az-text outline-none"
          />
        </div>
      </div>
      <div onMouseDown={leftPanel.onMouseDown} className="w-1 cursor-col-resize bg-az-border hover:bg-az-orange shrink-0" />

      {/* Main area */}
      <div className="flex-1 min-w-0 min-h-0 flex flex-col overflow-hidden">
        {/* Filter bar */}
        <div className="flex items-center gap-2 p-2 border-b border-az-border bg-az-panel text-xs flex-wrap">
          <input type="date" value={fromDate} onChange={e => setFromDate(e.target.value)} className="bg-az-bg border border-az-border rounded px-2 py-1 text-az-text" />
          <input type="date" value={toDate} onChange={e => setToDate(e.target.value)} className="bg-az-bg border border-az-border rounded px-2 py-1 text-az-text" />
          {statusButtons.map(sb => (
            <button
              key={String(sb.value)}
              onClick={() => { setStatusFilter(sb.value); setPage(1) }}
              className={`px-2 py-0.5 rounded ${statusFilter === sb.value ? 'bg-az-orange text-white' : 'bg-az-bg text-az-muted'}`}
            >
              {sb.label}
            </button>
          ))}
          <div className="flex-1" />
          {selectedIds.size > 0 && (
            <button onClick={handleValidate} className="bg-az-green text-white px-2 py-0.5 rounded">
              {t('dataset.validate')} ({selectedIds.size})
            </button>
          )}
        </div>

        {/* Tabs */}
        <div className="flex border-b border-az-border bg-az-panel">
          {(['annotations', 'editor', 'distribution'] as Tab[]).map(tb => (
            <button
              key={tb}
              onClick={() => setTab(tb)}
              className={`px-3 py-1.5 text-xs ${tab === tb ? 'bg-az-bg text-white border-b-2 border-az-orange' : 'text-az-muted'}`}
            >
              {t(`dataset.${tb === 'distribution' ? 'classDistribution' : tb}`)}
            </button>
          ))}
        </div>

        {/* Content */}
        {tab === 'annotations' && (
          <div className="flex-1 overflow-y-auto p-2">
            <div className="grid gap-2" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))' }}>
              {cards.map(card => {
                const statusPill =
                  card.status === AnnotationStatus.Validated ? { cls: 'bg-az-green text-white', label: t('dataset.status.validated') } :
                  card.status === AnnotationStatus.Edited ? { cls: 'bg-az-blue text-white', label: t('dataset.status.edited') } :
                  { cls: 'bg-az-orange text-white', label: t('dataset.status.created') }
                const isSelected = selectedIds.has(card.annotationId)
                return (
                  <div
                    key={card.annotationId}
                    onClick={e => {
                      if (e.ctrlKey) {
                        setSelectedIds(prev => {
                          const n = new Set(prev)
                          n.has(card.annotationId) ? n.delete(card.annotationId) : n.add(card.annotationId)
                          return n
                        })
                      } else {
                        setSelectedIds(new Set([card.annotationId]))
                      }
                    }}
                    onDoubleClick={() => handleDoubleClick(card)}
                    onContextMenu={e => {
                      if (!card.isLocal) return
                      e.preventDefault()
                      removeSaved(card.annotationId)
                    }}
                    title={card.imageName}
                    className={`aspect-square bg-az-panel rounded border overflow-hidden cursor-pointer relative transition-colors ${
                      isSelected ? 'border-az-orange' : 'border-az-border hover:border-az-blue'
                    } ${card.isSeed ? 'ring-2 ring-az-red' : ''}`}
                  >
                    {card.thumbnailUrl ? (
                      <img
                        src={card.thumbnailUrl}
                        alt={card.imageName}
                        className="w-full h-full object-cover bg-az-bg"
                        loading="lazy"
                      />
                    ) : (
                      <div className="w-full h-full bg-az-bg" />
                    )}
                    <span className={`absolute bottom-1.5 left-1.5 text-[10px] px-2 py-0.5 rounded-full ${statusPill.cls}`}>
                      {statusPill.label}
                    </span>
                    {card.isLocal && (
                      <span className="absolute top-1.5 right-1.5 text-[9px] px-1.5 py-0.5 rounded bg-az-border text-az-text">
                        local
                      </span>
                    )}
                    <button
                      type="button"
                      onClick={e => { e.stopPropagation(); handleDoubleClick(card) }}
                      title={t('dataset.edit') ?? 'Edit'}
                      className="absolute bottom-1.5 right-1.5 w-6 h-6 flex items-center justify-center rounded bg-az-bg/80 text-az-text hover:bg-az-orange hover:text-white"
                    >
                      <FaPen size={10} />
                    </button>
                  </div>
                )
              })}
            </div>
            {cards.length === 0 && (
              <div className="text-center text-az-muted text-xs py-8">{t('common.noData')}</div>
            )}
            {/* Pagination */}
            {totalPages > 1 && (
              <div className="flex justify-center gap-2 py-3">
                <button onClick={() => setPage(p => Math.max(1, p - 1))} disabled={page === 1} className="text-xs text-az-muted disabled:opacity-30 px-2 py-1 bg-az-panel rounded">Prev</button>
                <span className="text-xs text-az-text py-1">{page} / {totalPages}</span>
                <button onClick={() => setPage(p => Math.min(totalPages, p + 1))} disabled={page === totalPages} className="text-xs text-az-muted disabled:opacity-30 px-2 py-1 bg-az-panel rounded">Next</button>
              </div>
            )}
          </div>
        )}

        {tab === 'editor' && editorMedia && editorAnnotation && (
          <div className="flex-1 min-h-0 relative overflow-hidden">
            <div className="absolute inset-0 flex flex-col">
              <div className="bg-az-panel border-b border-az-border px-2 py-1 flex gap-2 items-center shrink-0">
                <button
                  onClick={handleEditorSave}
                  disabled={editorSaving || (!editorLocalGroupId && editorDetections.length === 0)}
                  className="px-2.5 py-1 rounded border border-az-green text-az-green text-[11px] hover:bg-az-green/10 disabled:opacity-40 disabled:cursor-not-allowed"
                >
                  {editorSaving ? 'Saving…' : t('common.save') ?? 'Save'}
                </button>
                <button
                  onClick={handleEditorCancel}
                  disabled={editorSaving}
                  className="px-2.5 py-1 rounded border border-az-border text-az-text text-[11px] hover:bg-az-border/30 disabled:opacity-40"
                >
                  {t('common.cancel') ?? 'Cancel'}
                </button>
                <span className="text-az-muted text-[10px]">
                  {editorDetections.length} detection{editorDetections.length !== 1 ? 's' : ''}
                </span>
                {!editorLocalGroupId && (
                  <span className="text-az-muted text-[10px] ml-auto">
                    remote save not wired yet
                  </span>
                )}
              </div>
              <div className="flex-1 min-h-0 relative">
                <div className="absolute inset-0">
                  <CanvasEditor
                    media={editorMedia}
                    annotation={editorAnnotation}
                    detections={editorDetections}
                    onDetectionsChange={setEditorDetections}
                    selectedClassNum={selectedClassNum}
                    currentTime={0}
                    annotations={[]}
                  />
                </div>
              </div>
            </div>
          </div>
        )}

        {tab === 'distribution' && (
          <div className="flex-1 overflow-y-auto bg-az-bg">
            {distribution.map(d => {
              const pct = (d.count / maxDistCount) * 100
              return (
                <div key={d.classNum} className="relative h-6 border-b border-az-border/40">
                  <div
                    className="absolute inset-y-0 left-0"
                    style={{ width: `${pct}%`, backgroundColor: d.color, opacity: 0.85 }}
                  />
                  <div className="relative flex items-center justify-between h-full px-2 text-xs text-white tabular-nums">
                    <span className="truncate">{d.label}: {d.count}</span>
                    <span className="pl-2">{d.count}</span>
                  </div>
                </div>
              )
            })}
          </div>
        )}
      </div>
    </div>
  )
}
