import { useState, useMemo } from 'react'
import {
  X,
  Star,
  MapPin,
  Camera,
  Aperture,
  Info,
  ChevronDown,
  ChevronRight,
  Check,
} from 'lucide-react'
import clsx from 'clsx'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { format } from 'date-fns'
import { usePhotoStore } from '../../store/photoStore'
import { photos as photosApi } from '../../services/api'

interface PhotoDetails {
  id: string
  filename: string
  filepath: string
  width: number | null
  height: number | null
  file_size: number | null
  taken_at: string | null
  rating: number
  is_picked: boolean
  is_rejected: boolean
  exif_json: string | null
}

interface ExifData {
  Make?: string
  Model?: string
  LensModel?: string
  Lens?: string
  ISO?: number | string
  FNumber?: number | string
  ApertureValue?: number | string
  ExposureTime?: string
  ShutterSpeedValue?: string
  FocalLength?: string
  FocalLengthIn35mmFormat?: string
  GPSLatitude?: number | string
  GPSLongitude?: number | string
  [key: string]: unknown
}

function formatFileSize(bytes: number | null): string {
  if (bytes == null) return '—'
  if (bytes < 1024) return `${bytes} B`
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`
  return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`
}

function formatExifValue(v: unknown): string {
  if (v == null || v === '') return '—'
  return String(v)
}

function pickFirst(exif: ExifData, ...keys: string[]): string {
  for (const k of keys) {
    const v = exif[k]
    if (v != null && v !== '') return String(v)
  }
  return '—'
}

function parseExif(json: string | null): ExifData {
  if (!json) return {}
  try {
    const parsed = JSON.parse(json)
    return typeof parsed === 'object' && parsed !== null ? (parsed as ExifData) : {}
  } catch {
    return {}
  }
}

export function RightSidebar() {
  const { selectedPhotos, activePhotoId, clearSelection } = usePhotoStore()
  const queryClient = useQueryClient()

  const [expandedSections, setExpandedSections] = useState<Set<string>>(
    new Set(['basic', 'camera', 'location'])
  )

  const toggleSection = (section: string) => {
    const newExpanded = new Set(expandedSections)
    if (newExpanded.has(section)) newExpanded.delete(section)
    else newExpanded.add(section)
    setExpandedSections(newExpanded)
  }

  // Fetch the active photo's full record (with EXIF) on demand.
  const { data: photo } = useQuery<PhotoDetails>({
    queryKey: ['photo', activePhotoId],
    queryFn: () => photosApi.get(activePhotoId!),
    enabled: !!activePhotoId,
    staleTime: 60_000,
  })

  // Mutations for rating / pick / reject. Optimistic-ish: invalidate the
  // photo query and the timeline list query so the grid re-renders too.
  const updateMutation = useMutation({
    mutationFn: (data: {
      rating?: number
      is_picked?: boolean
      is_rejected?: boolean
    }) => photosApi.update(activePhotoId!, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['photo', activePhotoId] })
      queryClient.invalidateQueries({ queryKey: ['photos'] })
    },
  })

  const exif = useMemo(() => parseExif(photo?.exif_json ?? null), [photo?.exif_json])

  if (selectedPhotos.length === 0) {
    return (
      <div className="flex h-full items-center justify-center p-4 text-center">
        <div className="text-text-muted">
          <Info className="mx-auto mb-2 h-8 w-8" />
          <p className="text-sm">Select photos to view details</p>
        </div>
      </div>
    )
  }

  const multipleSelected = selectedPhotos.length > 1
  const rating = photo?.rating ?? 0
  const isPicked = photo?.is_picked ?? false
  const isRejected = photo?.is_rejected ?? false

  return (
    <div className="flex h-full flex-col bg-surface">
      {/* Header */}
      <div className="flex items-center justify-between border-b border-border px-4 py-3">
        <h2 className="text-sm font-semibold text-text">
          {multipleSelected
            ? `${selectedPhotos.length} Photos Selected`
            : 'Photo Details'}
        </h2>
        <button
          onClick={clearSelection}
          className="rounded p-1 text-text-muted hover:bg-surface-2 hover:text-text"
          title="Clear selection"
        >
          <X className="h-4 w-4" />
        </button>
      </div>

      {/* Quick Actions — operate on the active photo */}
      {photo && !multipleSelected && (
        <div className="border-b border-border p-4">
          <div className="mb-3">
            <label className="mb-1 block text-xs text-text-muted">Rating</label>
            <div className="flex gap-1">
              {[1, 2, 3, 4, 5].map((value) => (
                <button
                  key={value}
                  onClick={() =>
                    updateMutation.mutate({ rating: rating === value ? 0 : value })
                  }
                  className="p-0.5"
                  title={`Set rating to ${value}`}
                >
                  <Star
                    className={clsx(
                      'h-5 w-5 transition-colors',
                      value <= rating
                        ? 'fill-star text-star'
                        : 'text-text-muted hover:text-star'
                    )}
                  />
                </button>
              ))}
            </div>
          </div>

          <div>
            <label className="mb-1 block text-xs text-text-muted">Flag</label>
            <div className="flex gap-2">
              <button
                onClick={() =>
                  updateMutation.mutate({
                    is_picked: !isPicked,
                    is_rejected: false,
                  })
                }
                className={clsx(
                  'flex items-center gap-1 rounded px-2 py-1 text-sm transition-colors',
                  isPicked
                    ? 'bg-pick/20 text-pick'
                    : 'bg-surface-2 text-text-muted hover:bg-surface-offset'
                )}
              >
                <Check className="h-3 w-3" />
                Pick
              </button>
              <button
                onClick={() =>
                  updateMutation.mutate({
                    is_rejected: !isRejected,
                    is_picked: false,
                  })
                }
                className={clsx(
                  'flex items-center gap-1 rounded px-2 py-1 text-sm transition-colors',
                  isRejected
                    ? 'bg-reject/20 text-reject'
                    : 'bg-surface-2 text-text-muted hover:bg-surface-offset'
                )}
              >
                <X className="h-3 w-3" />
                Reject
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Metadata */}
      <div className="flex-1 overflow-y-auto">
        {photo && !multipleSelected && (
          <>
            {/* Basic Info */}
            <Section
              title="Basic Info"
              expanded={expandedSections.has('basic')}
              onToggle={() => toggleSection('basic')}
            >
              <div className="grid grid-cols-2 gap-2 text-xs">
                <Field label="Filename" value={photo.filename} />
                <Field label="Size" value={formatFileSize(photo.file_size)} />
                <Field
                  label="Dimensions"
                  value={
                    photo.width && photo.height
                      ? `${photo.width} × ${photo.height}`
                      : '—'
                  }
                />
                <Field
                  label="Date Taken"
                  value={
                    photo.taken_at
                      ? format(new Date(photo.taken_at), 'MMM d, yyyy HH:mm')
                      : '—'
                  }
                />
              </div>
            </Section>

            {/* Camera */}
            <Section
              title="Camera"
              expanded={expandedSections.has('camera')}
              onToggle={() => toggleSection('camera')}
            >
              <div className="space-y-1 text-xs">
                <div className="flex items-center gap-2">
                  <Camera className="h-3 w-3 text-text-muted" />
                  <span className="text-text">
                    {pickFirst(exif, 'Make', 'Model') === '—'
                      ? '—'
                      : `${formatExifValue(exif.Make)} ${formatExifValue(exif.Model)}`.trim()}
                  </span>
                </div>
                <div className="flex items-center gap-2">
                  <Aperture className="h-3 w-3 text-text-muted" />
                  <span className="text-text">
                    {pickFirst(exif, 'LensModel', 'Lens')}
                  </span>
                </div>
                <div className="mt-2 grid grid-cols-2 gap-2">
                  <Field label="ISO" value={formatExifValue(exif.ISO)} />
                  <Field
                    label="Aperture"
                    value={
                      exif.FNumber
                        ? `f/${exif.FNumber}`
                        : pickFirst(exif, 'ApertureValue')
                    }
                  />
                  <Field
                    label="Shutter"
                    value={pickFirst(exif, 'ExposureTime', 'ShutterSpeedValue')}
                  />
                  <Field
                    label="Focal"
                    value={pickFirst(
                      exif,
                      'FocalLength',
                      'FocalLengthIn35mmFormat'
                    )}
                  />
                </div>
              </div>
            </Section>

            {/* Location */}
            <Section
              title="Location"
              expanded={expandedSections.has('location')}
              onToggle={() => toggleSection('location')}
            >
              {exif.GPSLatitude && exif.GPSLongitude ? (
                <div className="flex items-center gap-2 text-xs">
                  <MapPin className="h-3 w-3 text-text-muted" />
                  <span className="font-mono text-text">
                    {String(exif.GPSLatitude)}, {String(exif.GPSLongitude)}
                  </span>
                </div>
              ) : (
                <div className="text-xs text-text-muted">No GPS data</div>
              )}
            </Section>
          </>
        )}

        {!photo && !multipleSelected && (
          <div className="p-4 text-xs text-text-muted">Loading…</div>
        )}
      </div>

      {/* Footer Actions for multi-select */}
      {multipleSelected && (
        <div className="border-t border-border p-3">
          <div className="space-y-2">
            <button className="w-full rounded bg-surface-2 px-3 py-1.5 text-sm text-text hover:bg-surface-offset">
              Add to Heap
            </button>
            <button className="w-full rounded bg-surface-2 px-3 py-1.5 text-sm text-text hover:bg-surface-offset">
              Export Selected
            </button>
          </div>
        </div>
      )}
    </div>
  )
}

function Section({
  title,
  expanded,
  onToggle,
  children,
}: {
  title: string
  expanded: boolean
  onToggle: () => void
  children: React.ReactNode
}) {
  return (
    <div className="border-b border-border">
      <button
        onClick={onToggle}
        className="flex w-full items-center justify-between px-4 py-2 text-sm hover:bg-surface-2"
      >
        <span className="font-medium text-text">{title}</span>
        {expanded ? (
          <ChevronDown className="h-4 w-4 text-text-muted" />
        ) : (
          <ChevronRight className="h-4 w-4 text-text-muted" />
        )}
      </button>
      {expanded && <div className="px-4 pb-3">{children}</div>}
    </div>
  )
}

function Field({ label, value }: { label: string; value: string }) {
  return (
    <div>
      <span className="text-text-muted">{label}:</span>
      <p className="break-words text-text">{value}</p>
    </div>
  )
}
