import { DeckTooltipLayer } from './DeckTooltip'
import { CiCoverageBanner } from './CiCoverageBanner'
import { resolveTrainRepoGap, type CiRepoCompleteness } from './ci-coverage'
import { TrainCard, type TrainCardProps, type TrainViewModel } from './TrainCard'

export interface TrainRepoCompleteness extends CiRepoCompleteness {}

export interface TrainRailProps extends Pick<TrainCardProps, 'onAction' | 'onOpen'> {
  trains: TrainViewModel[]
  repos: TrainRepoCompleteness[]
}

function optionalNumberDesc(left: number | null, right: number | null): number {
  if (left === null) return right === null ? 0 : 1
  if (right === null) return -1
  return right - left
}

function trainNumber(branch: string): number | null {
  const match = branch.match(/batch-train-(\d+)$/)
  if (!match) return null
  const value = Number(match[1])
  return Number.isSafeInteger(value) ? value : null
}

function createdAtValue(value: string | null): number | null {
  if (value === null) return null
  const timestamp = Date.parse(value)
  return Number.isFinite(timestamp) ? timestamp : null
}

function ascending(left: string, right: string): number {
  return left < right ? -1 : left > right ? 1 : 0
}

export function compareTrains(left: TrainViewModel, right: TrainViewModel): number {
  return (
    optionalNumberDesc(trainNumber(left.branch), trainNumber(right.branch)) ||
    optionalNumberDesc(createdAtValue(left.createdAt), createdAtValue(right.createdAt)) ||
    optionalNumberDesc(left.prNumber, right.prNumber) ||
    ascending(left.branch, right.branch) ||
    ascending(left.repo, right.repo)
  )
}

function repoGap(repo: TrainRepoCompleteness) {
  return resolveTrainRepoGap(repo)
}

export function TrainRail({ trains, repos, onAction, onOpen }: TrainRailProps) {
  const visibleTrains = trains.filter((train) => train.state !== 'merged').sort(compareTrains)
  const gaps = repos.flatMap((repo) => {
    const gap = repoGap(repo)
    return gap ? [gap] : []
  })

  return (
    <section aria-label="Merge trains" className="min-w-0">
      {gaps.length > 0 && (
        <div className="mb-3 space-y-2">
          {repos.map((repo) => {
            const gap = repoGap(repo)
            return gap ? <CiCoverageBanner key={gap.id} gaps={[gap]} repoPrefix={repo.repo} /> : null
          })}
        </div>
      )}
      {visibleTrains.length > 0 ? (
        <div className="flex gap-3 overflow-x-auto pb-2">
          {visibleTrains.map((train) => (
            <TrainCard
              key={`${train.repo}:${train.branch}:${train.prNumber ?? 'branch'}`}
              train={train}
              onAction={onAction}
              onOpen={onOpen}
            />
          ))}
        </div>
      ) : gaps.length === 0 ? (
        <p role="status" className="rounded-xl border border-border bg-surface p-4 text-sm text-fg-muted">
          No trains. Queue &gt;2 green-intent PRs? → assemble a train
        </p>
      ) : null}
      <DeckTooltipLayer />
    </section>
  )
}
