import {
  AmplificationSpark,
  ClusterQueue,
  InboxItem,
  KpiTile,
  OffloadControl,
  PrQueueTable,
  RepoCiStrip,
  RemoteJobsTable,
  RunnerFleetStrip,
  SectionCard,
  StaleBadge,
  TrainRail,
} from '@overdeck/deck-ui'
import { ToastProvider, useToast } from '@platform-modules/ui-primitives/Toast'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { postCollectorAction } from '../../lib/action-client'
import { MachinesWidget } from '../machines/MachinesWidget'
export { buildOffloadActionArgs } from '../machines/MachinesWidget'
import { useCollectorItems, useCollectorState } from '../../lib/collector-queries'
import type { GhciPanelData } from '../../lib/panel-data'
import { ciKvRows } from '../../lib/page-mappers'
import { severityDotFor } from '../inbox/inbox-mappers'
import {
  buildItems,
  amplificationProps,
  clusterQueueFromPanel,
  fleetFromPanel,
  hostChipSummary,
  offloadControlFromPanel,
  incidentAlertActions,
  offloadKpiTiles,
  panelById,
  prQueueItems,
  prQueueRepoCompleteness,
  remoteJobsFromPanel,
  repoCiSummaries,
  runnerFleetFromPanel,
  stalledQueueItem,
  trainModels,
  trainRepoCompleteness,
} from './ci-mappers'

export function CiContent() {
  return (
    <ToastProvider>
      <CiContentInner />
    </ToastProvider>
  )
}

function CiContentInner() {
  const { toast } = useToast()
  const stateQuery = useCollectorState()
  const itemsQuery = useCollectorItems('build')

  const panels = stateQuery.data?.panels ?? []
  const adapters = stateQuery.data?.adapters ?? []
  const buildKindItems = itemsQuery.data?.items ?? buildItems([])

  const control = useMemo(() => offloadControlFromPanel(panels), [panels])
  const queue = useMemo(() => clusterQueueFromPanel(panels), [panels])
  const fleet = useMemo(() => fleetFromPanel(panels), [panels])
  const jobs = useMemo(() => remoteJobsFromPanel(panels), [panels])
  const kpis = useMemo(() => offloadKpiTiles(queue, buildKindItems), [queue, buildKindItems])
  const stalled = useMemo(() => stalledQueueItem(buildKindItems), [buildKindItems])
  const ciData = panelById<GhciPanelData>(panels, 'ci')
  const offloadStatus = adapters.find((adapter) => adapter.id === 'offload')

  const [selectedRepo, setSelectedRepo] = useState<string | null>(null)
  const repos = useMemo(() => ciData?.repos ?? [], [ciData])
  const scopedRepos = useMemo(() => selectedRepo === null ? repos : repos.filter((repo) => repo.repo === selectedRepo), [repos, selectedRepo])
  const repoSummaries = useMemo(() => repoCiSummaries(ciData ?? { repos: [], runners: [], runnersComplete: false, oldestQueuedAgeH: null }), [ciData])
  const trains = useMemo(() => trainModels(scopedRepos), [scopedRepos])
  const trainRepos = useMemo(() => trainRepoCompleteness(scopedRepos), [scopedRepos])
  const prs = useMemo(() => prQueueItems(scopedRepos), [scopedRepos])
  const prRepos = useMemo(() => prQueueRepoCompleteness(scopedRepos), [scopedRepos])
  const runnerFleet = useMemo(() => runnerFleetFromPanel(ciData), [ciData])
  const hostChips = useMemo(() => hostChipSummary(fleet, control), [fleet, control])

  useEffect(() => {
    if (selectedRepo !== null && !repos.some((repo) => repo.repo === selectedRepo)) setSelectedRepo(null)
  }, [repos, selectedRepo])

  const onTrainAction = useCallback((verb: string, args: Record<string, string>) => {
    const label = verb === 'ci.rerunFailed' ? 'Rerun failed' : 'Cancel superseded'
    void postCollectorAction(verb, { args, requestedBy: 'overdeck-web' })
      .then((response) => {
        toast({
          title: `${label} succeeded`,
          description: typeof response.result === 'string' ? response.result : undefined,
          tone: 'success',
        })
      })
      .catch((error: unknown) => {
        toast({
          title: `${label} failed`,
          description: error instanceof Error ? error.message : String(error),
          tone: 'danger',
        })
      })
  }, [toast])

  const onTrainOpen = useCallback((value: string) => {
    try {
      const url = new URL(value)
      if (
        url.protocol !== 'https:'
        || url.hostname !== 'github.com'
        || url.username !== ''
        || url.password !== ''
      ) throw new Error('invalid')
      window.location.assign(value)
    } catch {
      toast({ title: 'Open failed', description: 'Invalid GitHub URL', tone: 'danger' })
    }
  }, [toast])

  if (stateQuery.isLoading) return <div className="text-fg-muted">Loading CI & Build…</div>

  return (
    <div className="flex flex-col gap-3.5" data-testid="ci-build-page">
      <RunnerFleetStrip {...runnerFleet} />
      <RepoCiStrip repos={repoSummaries} selectedRepo={selectedRepo} onScope={setSelectedRepo} />
      <TrainRail trains={trains} repos={trainRepos} onAction={onTrainAction} onOpen={onTrainOpen} />
      <PrQueueTable prs={prs} repos={prRepos} allScope={selectedRepo === null} />
      {scopedRepos.map((repo) => (
        <AmplificationSpark key={repo.repo} {...amplificationProps(repo)} />
      ))}

      <div className="flex flex-col gap-3.5" data-testid="ci-build-offload">
      <div className="flex flex-wrap items-center gap-3.5">
        {control ? (
          <span className="inline-flex items-center gap-[7px] rounded-[20px] border border-border bg-surface px-[11px] py-1 text-[11.5px] text-fg-muted">
            <i className="h-[7px] w-[7px] rounded-full bg-success" />
            offload: {control.observed} · rev {control.revision}
          </span>
        ) : <div className="text-[12px] text-fg-muted">Offload control not recorded.</div>}
        {panels.some((panel) => panel.id === 'fleet') ? (
          <div className="text-[11.5px] text-fg-muted" data-testid="ci-build-host-chips">
            {hostChips.map((chip) => (
              <span key={chip} className="mr-3">
                {chip}
              </span>
            ))}
          </div>
        ) : null}
      </div>

      {stalled ? (
        <div className="flex items-start gap-3 rounded-xl border border-danger border-l-4 border-l-danger bg-surface px-4 py-3.5">
          <div className="grid h-[30px] w-[30px] flex-shrink-0 place-items-center rounded-lg bg-[var(--mod-color-nhot-bg)] text-danger">
            ▲
          </div>
          <div className="min-w-0 flex-1">
            <div className="text-[13.5px] font-bold">{stalled.title}</div>
            <div className="mt-0.5 text-[12px] leading-relaxed text-fg-muted">{stalled.detail}</div>
          </div>
          <div className="ml-auto flex flex-shrink-0 flex-wrap justify-end gap-1.5">
            {incidentAlertActions(stalled).map((action) => (
              <button
                key={action.label}
                type="button"
                data-action-verb={action.verb}
                disabled
                title="Actions land in wave 4"
                className={
                  action.primary
                    ? 'cursor-not-allowed rounded-[7px] border border-[var(--mod-color-accent-tint)] bg-[var(--mod-color-accent-tint)] px-3 py-1 text-[11.5px] font-semibold text-accent-fg opacity-50'
                    : 'cursor-not-allowed rounded-[7px] border border-border-strong bg-surface-raised px-3 py-1 text-[11.5px] text-fg opacity-50'
                }
              >
                {action.label}
              </button>
            ))}
          </div>
        </div>
      ) : null}

      <div className="grid grid-cols-6 gap-3">
        {kpis.map((tile) => (
          <div key={tile.key} data-testid={`offload-kpi-${tile.key}`} className="rounded-xl border border-border bg-surface px-[15px] py-[13px]">
            {tile.value === null ? (
              <div>
                <div className="text-[16px] font-semibold text-fg-muted">not recorded</div>
                <div className="mt-0.5 text-[12px] text-fg-muted">{tile.label}</div>
              </div>
            ) : <KpiTile tile={{ key: tile.key, label: tile.label, value: tile.value }} />}
            {tile.sub ? <div className="mt-[3px] text-[11px] leading-snug text-fg-subtle">{tile.sub}</div> : null}
          </div>
        ))}
      </div>

      <MachinesWidget panels={panels}>
        {({ control: machinesControl, selectedMachine, onAction, pendingVerb, actionError }) => <>
      <div className="grid grid-cols-[1fr_1.35fr] gap-3">

        <SectionCard
          title="Offload control"
          titleBadge={offloadStatus ? <StaleBadge status={offloadStatus} /> : undefined}
          action={{ label: 'history →' }}
        >
          {machinesControl ? (
            <OffloadControl
              control={machinesControl}
              selectedHost={selectedMachine}
              onAction={(action) => onAction(action, selectedMachine)}
              pendingVerb={pendingVerb}
              actionError={actionError}
            />
          ) : (
            <div className="text-[12px] text-fg-muted">Offload control not recorded.</div>
          )}
        </SectionCard>
        <SectionCard
          title="Cluster queue"
          titleBadge={offloadStatus ? <StaleBadge status={offloadStatus} /> : undefined}
        >
          {queue ? <ClusterQueue queue={queue} /> : <div className="text-[12px] text-fg-muted">Cluster queue not recorded.</div>}
        </SectionCard>
      </div>

      <SectionCard title={queue?.dispatchTarget ? `Remote jobs (${queue.dispatchTarget})` : 'Remote jobs'} action={{ label: 'rb-* units →' }}>
        {jobs
          ? <RemoteJobsTable jobs={jobs} hostLabel={queue?.dispatchTarget} />
          : <div className="text-[12px] text-fg-muted">Remote jobs not recorded.</div>}
      </SectionCard>

      <div className="grid grid-cols-2 gap-3">
        <SectionCard title="CI runners" action={{ label: 'workflows →' }}>
          {ciData ? <CiRunnersSummary data={ciData} /> : <div className="text-[12px] text-fg-muted">No CI panel.</div>}
        </SectionCard>
        <SectionCard title="Incidents" action={{ label: 'all →' }}>
          <div data-testid="ci-build-incidents">
            {buildKindItems.map((item, index) => (
              <InboxItem
                key={item.id}
                dot={severityDotFor(item.severity)}
                title={item.title}
                subtitle={item.detail}
                isLast={index === buildKindItems.length - 1}
                actions={item.actions.map((action) => ({
                  label: action.label,
                  primary: action.recommended,
                  verb: action.verb,
                }))}
              />
            ))}
          </div>
        </SectionCard>
      </div>

        </>}
      </MachinesWidget>
      </div>
    </div>
  )
}

function CiRunnersSummary({ data }: { data: GhciPanelData }) {
  const rows = ciKvRows(data)
  return (
    <div>
      {rows.map((row) => (
        <div key={row.label} className="flex justify-between border-b border-[#1d2027] py-1 text-[12px] text-fg-muted">
          <span>{row.label}</span>
          <b className="font-medium text-fg">{row.value}</b>
        </div>
      ))}
    </div>
  )
}
