import { useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import { useTimeline } from '../api/queries/timeline'
import { Skeleton } from '../ui/Skeleton'
import { cn } from '../lib/utils'
import type { TimelineEvent, CommitEvent, RunEvent, DeploymentEvent } from '../types/api'

// ── Utilities ─────────────────────────────────────────────────────────────────

function timeAgo(iso: string): string {
  const diff = Date.now() - new Date(iso).getTime()
  const min = Math.floor(diff / 60_000)
  if (min < 1) return 'just now'
  if (min < 60) return `${min}m ago`
  const hr = Math.floor(min / 60)
  if (hr < 24) return `${hr}h ago`
  const d = Math.floor(hr / 24)
  if (d < 30) return `${d}d ago`
  return new Date(iso).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })
}

function formatDate(iso: string): string {
  return new Date(iso).toLocaleDateString('en-US', {
    weekday: 'long', month: 'long', day: 'numeric', year: 'numeric',
  })
}

function duration(start: string | null | undefined, end: string | null | undefined): string {
  if (!start) return ''
  const ms = new Date(end ?? Date.now()).getTime() - new Date(start).getTime()
  const s = Math.floor(ms / 1000)
  if (s < 60) return `${s}s`
  return `${Math.floor(s / 60)}m ${s % 60}s`
}

function shortSHA(sha: string) { return sha.slice(0, 7) }
function shortRef(ref: string) { return ref.replace('refs/heads/', '').replace('refs/tags/', '') }

// ── Day grouping ──────────────────────────────────────────────────────────────

function dayKey(iso: string): string {
  return new Date(iso).toISOString().slice(0, 10)
}

// ── Status helpers ─────────────────────────────────────────────────────────────

const RUN_LABEL: Record<string, string> = {
  queued: 'Queued', running: 'Running', succeeded: 'Passed',
  failed: 'Failed', cancelled: 'Cancelled',
}

const DEPLOY_LABEL: Record<string, string> = {
  pending: 'Pending', in_progress: 'In progress', success: 'Active',
  failure: 'Failed', cancelled: 'Cancelled',
}

// ── Event icons ───────────────────────────────────────────────────────────────

function CommitIcon() {
  return (
    <div className="w-7 h-7 rounded-full bg-[var(--c-surface)] border-2 border-[var(--c-border)] flex items-center justify-center shrink-0">
      <svg width="12" height="12" fill="none" stroke="var(--c-muted)" strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5" />
      </svg>
    </div>
  )
}

function RunIcon({ status }: { status: string }) {
  const isRunning = status === 'running'
  const isFailed = status === 'failed'
  const isPassed = status === 'succeeded'
  return (
    <div className={cn(
      'w-7 h-7 rounded-full border-2 flex items-center justify-center shrink-0',
      isPassed ? 'bg-[#E3FCEF] border-[#79F2C0]' :
      isFailed ? 'bg-[var(--c-danger-tint)] border-[#FF8F73]' :
      isRunning ? 'bg-[var(--c-brand-tint)] border-[var(--c-brand-focus)]' :
      'bg-[var(--c-surface)] border-[var(--c-border)]',
    )}>
      <svg width="12" height="12" fill="none"
        stroke={isPassed ? 'var(--c-success)' : isFailed ? 'var(--c-danger)' : isRunning ? 'var(--c-brand)' : 'var(--c-muted)'}
        strokeWidth="2" viewBox="0 0 24 24"
        className={isRunning ? 'animate-spin' : ''}
      >
        {isPassed
          ? <path strokeLinecap="round" strokeLinejoin="round" d="m4.5 12.75 6 6 9-13.5" />
          : isFailed
          ? <path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
          : isRunning
          ? <path strokeLinecap="round" d="M12 3a9 9 0 1 0 9 9" />
          : <path strokeLinecap="round" strokeLinejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z" />
        }
      </svg>
    </div>
  )
}

function DeployIcon({ status }: { status: string }) {
  const isSuccess = status === 'success'
  const isFailure = status === 'failure'
  const isActive = status === 'in_progress'
  return (
    <div className={cn(
      'w-7 h-7 rounded-full border-2 flex items-center justify-center shrink-0',
      isSuccess ? 'bg-[#E3FCEF] border-[#79F2C0]' :
      isFailure ? 'bg-[var(--c-danger-tint)] border-[#FF8F73]' :
      isActive  ? 'bg-[var(--c-brand-tint)] border-[var(--c-brand-focus)]' :
      'bg-[var(--c-surface)] border-[var(--c-border)]',
    )}>
      <svg width="12" height="12" fill="none"
        stroke={isSuccess ? 'var(--c-success)' : isFailure ? 'var(--c-danger)' : isActive ? 'var(--c-brand)' : 'var(--c-muted)'}
        strokeWidth="2" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 6 0m-6 0H3m16.5 0a3 3 0 0 0-3-3m3 3a3 3 0 1 1-6 0m6 0h1.5m-7.5 0h-3" />
      </svg>
    </div>
  )
}

// ── Event rows ─────────────────────────────────────────────────────────────────

function CommitRow({ ev, owner, repo }: { ev: CommitEvent; owner: string; repo: string }) {
  return (
    <div className="flex items-start gap-3">
      <CommitIcon />
      <div className="flex-1 min-w-0 pt-0.5">
        <p className="text-sm text-[var(--c-text)] leading-snug line-clamp-2">{ev.message}</p>
        <div className="flex items-center gap-2 mt-1 text-[11px] text-[var(--c-muted)] flex-wrap">
          <Link
            to={`/repos/${owner}/${repo}/commits`}
            className="font-mono text-[var(--c-brand)] hover:underline"
          >
            {shortSHA(ev.sha)}
          </Link>
          <span>by {ev.author}</span>
          <span>{timeAgo(ev.timestamp)}</span>
        </div>
      </div>
    </div>
  )
}

function RunRow({ ev, owner, repo }: { ev: RunEvent; owner: string; repo: string }) {
  const dur = duration(ev.startedAt, ev.finishedAt)
  return (
    <div className="flex items-start gap-3">
      <RunIcon status={ev.runStatus} />
      <div className="flex-1 min-w-0 pt-0.5">
        <div className="flex items-center gap-2 flex-wrap">
          <Link
            to={`/repos/${owner}/${repo}/runs/${ev.runId}`}
            className="text-sm font-medium text-[var(--c-text)] hover:text-[var(--c-brand)] transition-colors"
          >
            Run #{ev.runId}
          </Link>
          <span className={cn(
            'text-[10px] font-semibold',
            ev.runStatus === 'succeeded' ? 'text-[var(--c-success)]' :
            ev.runStatus === 'failed'    ? 'text-[var(--c-danger)]' :
            ev.runStatus === 'running'   ? 'text-[var(--c-brand)]' :
            'text-[var(--c-muted)]',
          )}>
            {RUN_LABEL[ev.runStatus] ?? ev.runStatus}
          </span>
        </div>
        <div className="flex items-center gap-2 mt-1 text-[11px] text-[var(--c-muted)] flex-wrap">
          <span className="font-mono">{shortRef(ev.triggerRef)}</span>
          <span className="font-mono">{shortSHA(ev.triggerSha)}</span>
          {dur && <span>{dur}</span>}
          <span>{timeAgo(ev.timestamp)}</span>
        </div>
      </div>
    </div>
  )
}

function DeployRow({ ev, owner, repo }: { ev: DeploymentEvent; owner: string; repo: string }) {
  return (
    <div className="flex items-start gap-3">
      <DeployIcon status={ev.deployStatus} />
      <div className="flex-1 min-w-0 pt-0.5">
        <div className="flex items-center gap-2 flex-wrap">
          <Link
            to={`/repos/${owner}/${repo}/environments`}
            className="text-sm font-medium text-[var(--c-text)] hover:text-[var(--c-brand)] transition-colors"
          >
            {ev.envName}
          </Link>
          <span className={cn(
            'text-[10px] font-semibold',
            ev.deployStatus === 'success'     ? 'text-[var(--c-success)]' :
            ev.deployStatus === 'failure'     ? 'text-[var(--c-danger)]' :
            ev.deployStatus === 'in_progress' ? 'text-[var(--c-brand)]' :
            'text-[var(--c-muted)]',
          )}>
            {DEPLOY_LABEL[ev.deployStatus] ?? ev.deployStatus}
          </span>
        </div>
        <div className="flex items-center gap-2 mt-1 text-[11px] text-[var(--c-muted)] flex-wrap">
          <span className="font-mono">{shortSHA(ev.deployedSha)}</span>
          {ev.deployRef && <span className="font-mono">{shortRef(ev.deployRef)}</span>}
          <span>by {ev.triggeredBy}</span>
          {ev.description && <span>· {ev.description}</span>}
          {ev.runLink && (
            <Link to={`/repos/${owner}/${repo}/runs/${ev.runLink}`} className="text-[var(--c-brand)] hover:underline">
              run #{ev.runLink}
            </Link>
          )}
          <span>{timeAgo(ev.timestamp)}</span>
        </div>
      </div>
    </div>
  )
}

// ── Filter bar ─────────────────────────────────────────────────────────────────

type Filter = 'all' | 'commit' | 'run' | 'deployment'

const FILTERS: { label: string; value: Filter }[] = [
  { label: 'All activity', value: 'all' },
  { label: 'Commits', value: 'commit' },
  { label: 'CI runs', value: 'run' },
  { label: 'Deployments', value: 'deployment' },
]

// ── Skeleton ──────────────────────────────────────────────────────────────────

function EventSkeleton() {
  return (
    <div className="flex items-start gap-3 py-3">
      <Skeleton className="w-7 h-7 rounded-full shrink-0" />
      <div className="flex-1 space-y-2 pt-0.5">
        <Skeleton className="h-3.5 w-3/4 rounded" />
        <Skeleton className="h-2.5 w-1/2 rounded" />
      </div>
    </div>
  )
}

// ── Page ──────────────────────────────────────────────────────────────────────

export default function RepoTimelinePage() {
  const { owner = '', repo = '' } = useParams()
  const { data: events, isLoading } = useTimeline(owner, repo)
  const [filter, setFilter] = useState<Filter>('all')

  const filtered = events?.filter(e => filter === 'all' || e.type === filter) ?? []

  // Group by calendar day
  const days: Array<{ key: string; label: string; events: TimelineEvent[] }> = []
  const dayMap = new Map<string, TimelineEvent[]>()
  for (const ev of filtered) {
    const k = dayKey(ev.timestamp)
    if (!dayMap.has(k)) dayMap.set(k, [])
    dayMap.get(k)!.push(ev)
  }
  for (const [k, evs] of dayMap) {
    days.push({ key: k, label: formatDate(evs[0].timestamp), events: evs })
  }

  const counts = {
    commit: events?.filter(e => e.type === 'commit').length ?? 0,
    run: events?.filter(e => e.type === 'run').length ?? 0,
    deployment: events?.filter(e => e.type === 'deployment').length ?? 0,
  }

  return (
    <div className="max-w-3xl mx-auto px-4 md:px-6 py-5 space-y-4">

      {/* Header */}
      <div>
        <h1 className="text-lg font-semibold text-[var(--c-text)]">Timeline</h1>
        <p className="text-xs text-[var(--c-muted)] mt-0.5">
          Commits, CI runs, and deployments for{' '}
          <span className="font-mono">{owner}/{repo}</span>
        </p>
      </div>

      {/* Filter tabs */}
      <div className="flex items-center gap-1 border-b border-[var(--c-border)]">
        {FILTERS.map(f => (
          <button
            key={f.value}
            onClick={() => setFilter(f.value)}
            className={cn(
              'px-3 py-2 text-xs font-medium border-b-2 -mb-px transition-colors',
              filter === f.value
                ? 'border-[var(--c-brand)] text-[var(--c-brand)]'
                : 'border-transparent text-[var(--c-muted)] hover:text-[var(--c-text)]',
            )}
          >
            {f.label}
            {f.value !== 'all' && !isLoading && (
              <span className="ml-1.5 text-[10px] font-mono text-[var(--c-subtle)]">
                {counts[f.value]}
              </span>
            )}
          </button>
        ))}
      </div>

      {/* Timeline */}
      {isLoading ? (
        <div className="space-y-1">
          {Array.from({ length: 8 }).map((_, i) => <EventSkeleton key={i} />)}
        </div>
      ) : filtered.length === 0 ? (
        <div className="flex flex-col items-center justify-center py-20 gap-3 text-center">
          <svg width="40" height="40" fill="none" stroke="var(--c-subtle)" strokeWidth="1" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
          </svg>
          <div>
            <p className="text-sm font-medium text-[var(--c-text)]">No activity yet</p>
            <p className="text-xs text-[var(--c-muted)] mt-1">
              {filter === 'all'
                ? 'Push commits, run pipelines, or create deployments to see activity here.'
                : `No ${filter === 'commit' ? 'commits' : filter === 'run' ? 'CI runs' : 'deployments'} yet.`}
            </p>
          </div>
        </div>
      ) : (
        <div className="space-y-6">
          {days.map(day => (
            <div key={day.key}>
              {/* Day separator */}
              <div className="flex items-center gap-3 mb-3">
                <div className="h-px flex-1 bg-[var(--c-border)]" />
                <span className="text-[10px] font-semibold uppercase tracking-wider text-[var(--c-muted)] shrink-0">
                  {day.label}
                </span>
                <div className="h-px flex-1 bg-[var(--c-border)]" />
              </div>

              {/* Events for this day */}
              <div className="relative">
                {/* Vertical line connecting events */}
                <div className="absolute left-3.5 top-7 bottom-0 w-px bg-[var(--c-border)]" aria-hidden />

                <div className="space-y-4">
                  {day.events.map((ev, i) => (
                    <div key={i} className="relative">
                      {ev.type === 'commit' && (
                        <CommitRow ev={ev as CommitEvent} owner={owner} repo={repo} />
                      )}
                      {ev.type === 'run' && (
                        <RunRow ev={ev as RunEvent} owner={owner} repo={repo} />
                      )}
                      {ev.type === 'deployment' && (
                        <DeployRow ev={ev as DeploymentEvent} owner={owner} repo={repo} />
                      )}
                    </div>
                  ))}
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  )
}
