import * as React from 'react'

import { cn } from './utils'

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface TimelineEvent {
  id: string
  timestamp: Date | string
  title: string
  description?: string
  icon?: string
  color?: string
  metadata?: Record<string, string>
}

export interface TimelineProps extends React.ComponentProps<'div'> {
  events: TimelineEvent[]
  orientation?: 'vertical' | 'horizontal'
  showTimestamps?: boolean
  dateFormat?: (date: Date) => string
  onEventClick?: (event: TimelineEvent) => void
  groupByDate?: boolean
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function toDate(val: Date | string): Date {
  return val instanceof Date ? val : new Date(val)
}

function defaultDateFormat(date: Date): string {
  return date.toLocaleString(undefined, {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}

function defaultGroupDateFormat(date: Date): string {
  return date.toLocaleDateString(undefined, {
    weekday: 'long',
    month: 'long',
    day: 'numeric',
    year: 'numeric',
  })
}

function dateKey(date: Date): string {
  const y = String(date.getFullYear())
  const m = String(date.getMonth() + 1).padStart(2, '0')
  const d = String(date.getDate()).padStart(2, '0')
  return `${y}-${m}-${d}`
}

// ---------------------------------------------------------------------------
// TimelineItem
// ---------------------------------------------------------------------------

interface TimelineItemProps {
  event: TimelineEvent
  showTimestamps: boolean
  dateFormat: (date: Date) => string
  onEventClick?: ((event: TimelineEvent) => void) | undefined
}

function TimelineItem({ event, showTimestamps, dateFormat, onEventClick }: TimelineItemProps) {
  return (
    <div
      className={cn(
        'bg-glass border-border-glass cursor-pointer rounded-lg border p-3 backdrop-blur-[20px] transition-all',
        'hover:border-border-glass/80 hover:shadow-sm'
      )}
      onClick={() => onEventClick?.(event)}
      onKeyDown={e => {
        if (e.key === 'Enter' || e.key === ' ') {
          e.preventDefault()
          onEventClick?.(event)
        }
      }}
      tabIndex={0}
      role="button"
      aria-label={event.title}
    >
      {/* Title */}
      <div className="text-foreground flex items-center gap-1.5 text-sm font-medium">
        {event.icon && (
          <span className="text-foreground-secondary" aria-hidden="true">
            {event.icon}
          </span>
        )}
        {event.title}
      </div>

      {/* Description */}
      {event.description && (
        <div className="text-foreground-secondary mt-1 text-xs">{event.description}</div>
      )}

      {/* Timestamp */}
      {showTimestamps && (
        <div className="text-foreground-secondary mt-1.5 text-[11px]">
          {dateFormat(toDate(event.timestamp))}
        </div>
      )}

      {/* Metadata */}
      {event.metadata && (
        <div className="mt-2 flex flex-wrap gap-x-3 gap-y-1">
          {Object.entries(event.metadata).map(([key, value]) => (
            <span key={key} className="text-[11px]">
              <span className="text-foreground-secondary">{key}:</span>{' '}
              <span className="text-foreground">{value}</span>
            </span>
          ))}
        </div>
      )}
    </div>
  )
}

// ---------------------------------------------------------------------------
// Timeline (vertical)
// ---------------------------------------------------------------------------

function VerticalTimeline({
  sorted,
  showTimestamps,
  dateFormat,
  groupByDate,
  onEventClick,
}: {
  sorted: TimelineEvent[]
  showTimestamps: boolean
  dateFormat: (date: Date) => string
  groupByDate: boolean
  onEventClick?: ((event: TimelineEvent) => void) | undefined
}) {
  if (groupByDate) {
    const groups = new Map<string, TimelineEvent[]>()
    const groupOrder: string[] = []
    for (const evt of sorted) {
      const key = dateKey(toDate(evt.timestamp))
      const existing = groups.get(key)
      if (existing) {
        existing.push(evt)
      } else {
        groups.set(key, [evt])
        groupOrder.push(key)
      }
    }

    return (
      <>
        {groupOrder.map(key => {
          const groupEvents = groups.get(key)!
          const firstEvent = groupEvents[0]!
          return (
            <React.Fragment key={key}>
              <div className="relative z-10 py-2">
                <span className="bg-surface-secondary text-foreground-secondary rounded-full px-3 py-1 text-xs font-medium">
                  {defaultGroupDateFormat(toDate(firstEvent.timestamp))}
                </span>
              </div>
              {groupEvents.map(evt => (
                <div key={evt.id} className="relative flex gap-4 pb-6" data-event-id={evt.id}>
                  {/* Dot */}
                  <div className="relative flex flex-col items-center">
                    <div
                      className="z-10 mt-1.5 size-3 shrink-0 rounded-full border-2 border-white/20"
                      style={{ background: evt.color ?? 'var(--color-accent-cyan, #06b6d4)' }}
                      aria-hidden="true"
                    />
                    <div className="bg-border-glass w-px flex-1" aria-hidden="true" />
                  </div>
                  {/* Content */}
                  <div className="min-w-0 flex-1 pb-1">
                    <TimelineItem
                      event={evt}
                      showTimestamps={showTimestamps}
                      dateFormat={dateFormat}
                      onEventClick={onEventClick}
                    />
                  </div>
                </div>
              ))}
            </React.Fragment>
          )
        })}
      </>
    )
  }

  return (
    <>
      {sorted.map(evt => (
        <div key={evt.id} className="relative flex gap-4 pb-6" data-event-id={evt.id}>
          {/* Dot */}
          <div className="relative flex flex-col items-center">
            <div
              className="z-10 mt-1.5 size-3 shrink-0 rounded-full border-2 border-white/20"
              style={{ background: evt.color ?? 'var(--color-accent-cyan, #06b6d4)' }}
              aria-hidden="true"
            />
            <div className="bg-border-glass w-px flex-1" aria-hidden="true" />
          </div>
          {/* Content */}
          <div className="min-w-0 flex-1 pb-1">
            <TimelineItem
              event={evt}
              showTimestamps={showTimestamps}
              dateFormat={dateFormat}
              onEventClick={onEventClick}
            />
          </div>
        </div>
      ))}
    </>
  )
}

// ---------------------------------------------------------------------------
// Timeline (horizontal)
// ---------------------------------------------------------------------------

function HorizontalTimeline({
  sorted,
  showTimestamps,
  dateFormat,
  onEventClick,
}: {
  sorted: TimelineEvent[]
  showTimestamps: boolean
  dateFormat: (date: Date) => string
  onEventClick?: ((event: TimelineEvent) => void) | undefined
}) {
  return (
    <div className="relative flex items-start gap-6 overflow-x-auto pb-4">
      {/* Horizontal line */}
      <div className="bg-border-glass absolute left-0 right-0 top-1.5 h-px" aria-hidden="true" />
      {sorted.map(evt => (
        <div
          key={evt.id}
          className="relative flex shrink-0 flex-col items-center"
          data-event-id={evt.id}
        >
          {/* Dot */}
          <div
            className="z-10 size-3 shrink-0 rounded-full border-2 border-white/20"
            style={{ background: evt.color ?? 'var(--color-accent-cyan, #06b6d4)' }}
            aria-hidden="true"
          />
          {/* Content */}
          <div className="mt-3 w-48">
            <TimelineItem
              event={evt}
              showTimestamps={showTimestamps}
              dateFormat={dateFormat}
              onEventClick={onEventClick}
            />
          </div>
        </div>
      ))}
    </div>
  )
}

// ---------------------------------------------------------------------------
// Timeline
// ---------------------------------------------------------------------------

function Timeline({
  events,
  orientation = 'vertical',
  showTimestamps = true,
  dateFormat = defaultDateFormat,
  onEventClick,
  groupByDate = false,
  className,
  ...props
}: TimelineProps) {
  const sorted = React.useMemo(
    () => [...events].sort((a, b) => toDate(a.timestamp).getTime() - toDate(b.timestamp).getTime()),
    [events]
  )

  return (
    <div data-slot="timeline" className={cn('relative', className)} {...props}>
      {orientation === 'horizontal' ? (
        <HorizontalTimeline
          sorted={sorted}
          showTimestamps={showTimestamps}
          dateFormat={dateFormat}
          onEventClick={onEventClick}
        />
      ) : (
        <VerticalTimeline
          sorted={sorted}
          showTimestamps={showTimestamps}
          dateFormat={dateFormat}
          groupByDate={groupByDate}
          onEventClick={onEventClick}
        />
      )}
    </div>
  )
}
Timeline.displayName = 'Timeline'

export { Timeline, TimelineItem }
