import { useState, useMemo } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import styles from './Dashboard.module.css'

// Layout
import { AppShell } from '../../design-system/layout/AppShell/AppShell'
import { Sidebar } from '../../design-system/layout/Sidebar/Sidebar'
import { TopBar } from '../../design-system/layout/TopBar/TopBar'

// Composites
import { DataTable } from '../../design-system/composites/DataTable/DataTable'
import type { Column } from '../../design-system/composites/DataTable/types'
import { DetailPanel } from '../../design-system/composites/DetailPanel/DetailPanel'
import { ShortcutsBar } from '../../design-system/composites/ShortcutsBar/ShortcutsBar'
import { ProcessorTimeline } from '../../design-system/composites/ProcessorTimeline/ProcessorTimeline'
import { RouteFlow } from '../../design-system/composites/RouteFlow/RouteFlow'
import type { RouteNode } from '../../design-system/composites/RouteFlow/RouteFlow'

// Primitives
import { StatCard } from '../../design-system/primitives/StatCard/StatCard'
import { StatusDot } from '../../design-system/primitives/StatusDot/StatusDot'
import { MonoText } from '../../design-system/primitives/MonoText/MonoText'
import { Badge } from '../../design-system/primitives/Badge/Badge'

// Global filters
import { useGlobalFilters } from '../../design-system/providers/GlobalFilterProvider'

// Mock data
import { exchanges, type Exchange } from '../../mocks/exchanges'
import { kpiMetrics } from '../../mocks/metrics'
import { SIDEBAR_APPS, buildRouteToAppMap } from '../../mocks/sidebar'

// Route → Application lookup
const ROUTE_TO_APP = buildRouteToAppMap()

// ─── Helpers ─────────────────────────────────────────────────────────────────
function formatDuration(ms: number): string {
  if (ms >= 60_000) return `${(ms / 1000).toFixed(0)}s`
  if (ms >= 1000) return `${(ms / 1000).toFixed(2)}s`
  return `${ms}ms`
}

function formatTimestamp(date: Date): string {
  const y = date.getFullYear()
  const mo = String(date.getMonth() + 1).padStart(2, '0')
  const d = String(date.getDate()).padStart(2, '0')
  const h = String(date.getHours()).padStart(2, '0')
  const mi = String(date.getMinutes()).padStart(2, '0')
  const s = String(date.getSeconds()).padStart(2, '0')
  return `${y}-${mo}-${d} ${h}:${mi}:${s}`
}

function statusToVariant(status: Exchange['status']): 'success' | 'error' | 'running' | 'warning' {
  switch (status) {
    case 'completed': return 'success'
    case 'failed': return 'error'
    case 'running': return 'running'
    case 'warning': return 'warning'
  }
}

function statusLabel(status: Exchange['status']): string {
  switch (status) {
    case 'completed': return 'OK'
    case 'failed': return 'ERR'
    case 'running': return 'RUN'
    case 'warning': return 'WARN'
  }
}

// ─── Table columns (base, without navigate action) ──────────────────────────
const BASE_COLUMNS: Column<Exchange>[] = [
  {
    key: 'status',
    header: 'Status',
    width: '80px',
    render: (_, row) => (
      <span className={styles.statusCell}>
        <StatusDot variant={statusToVariant(row.status)} />
        <MonoText size="xs">{statusLabel(row.status)}</MonoText>
      </span>
    ),
  },
  {
    key: 'route',
    header: 'Route',
    sortable: true,
    render: (_, row) => (
      <span className={styles.routeName}>{row.route}</span>
    ),
  },
  {
    key: 'routeGroup',
    header: 'Application',
    sortable: true,
    render: (_, row) => (
      <span className={styles.appName}>{ROUTE_TO_APP.get(row.route) ?? row.routeGroup}</span>
    ),
  },
  {
    key: 'id',
    header: 'Exchange ID',
    sortable: true,
    render: (_, row) => (
      <MonoText size="xs">{row.id}</MonoText>
    ),
  },
  {
    key: 'timestamp',
    header: 'Started',
    sortable: true,
    render: (_, row) => (
      <MonoText size="xs">{formatTimestamp(row.timestamp)}</MonoText>
    ),
  },
  {
    key: 'durationMs',
    header: 'Duration',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm" className={durationClass(row.durationMs, row.status)}>
        {formatDuration(row.durationMs)}
      </MonoText>
    ),
  },
  {
    key: 'agent',
    header: 'Agent',
    render: (_, row) => (
      <span className={styles.agentBadge}>
        <span className={styles.agentDot} />
        {row.agent}
      </span>
    ),
  },
]

function durationClass(ms: number, status: Exchange['status']): string {
  if (status === 'failed') return styles.durBreach
  if (ms < 100) return styles.durFast
  if (ms < 200) return styles.durNormal
  if (ms < 300) return styles.durSlow
  return styles.durBreach
}

const SHORTCUTS = [
  { keys: 'Ctrl+K', label: 'Search' },
  { keys: '↑↓', label: 'Navigate rows' },
  { keys: 'Enter', label: 'Open detail' },
  { keys: 'Esc', label: 'Close panel' },
]

// ─── Dashboard component ──────────────────────────────────────────────────────
export function Dashboard() {
  const { id: appId, routeId } = useParams<{ id: string; routeId: string }>()
  const navigate = useNavigate()
  const [selectedId, setSelectedId] = useState<string | undefined>()
  const [panelOpen, setPanelOpen] = useState(false)
  const [selectedExchange, setSelectedExchange] = useState<Exchange | null>(null)

  // Build columns with inspect action as second column
  const COLUMNS: Column<Exchange>[] = useMemo(() => {
    const inspectCol: Column<Exchange> = {
      key: 'correlationId' as keyof Exchange,
      header: '',
      width: '36px',
      render: (_, row) => (
        <button
          className={styles.inspectLink}
          title="Inspect exchange"
          onClick={(e) => {
            e.stopPropagation()
            navigate(`/exchanges/${row.id}`)
          }}
        >
          &#x2197;
        </button>
      ),
    }
    const [statusCol, ...rest] = BASE_COLUMNS
    return [statusCol, inspectCol, ...rest]
  }, [navigate])

  const { isInTimeRange, statusFilters } = useGlobalFilters()

  // Build set of route IDs belonging to the selected app (if any)
  const appRouteIds = useMemo(() => {
    if (!appId) return null
    const app = SIDEBAR_APPS.find((a) => a.id === appId)
    if (!app) return null
    return new Set(app.routes.map((r) => r.id))
  }, [appId])

  // Scope all data to the selected app (and optionally route)
  const scopedExchanges = useMemo(() => {
    if (routeId) return exchanges.filter((e) => e.route === routeId)
    if (!appRouteIds) return exchanges
    return exchanges.filter((e) => appRouteIds.has(e.route))
  }, [appRouteIds, routeId])

  // Filter exchanges (scoped + global filters)
  const filteredExchanges = useMemo(() => {
    let data = scopedExchanges

    // Time range filter
    data = data.filter((e) => isInTimeRange(e.timestamp))

    // Status filter
    if (statusFilters.size > 0) {
      data = data.filter((e) => statusFilters.has(e.status))
    }

    return data
  }, [scopedExchanges, isInTimeRange, statusFilters])

  function handleRowClick(row: Exchange) {
    setSelectedId(row.id)
    setSelectedExchange(row)
    setPanelOpen(true)
  }

  function handleRowAccent(row: Exchange): 'error' | 'warning' | undefined {
    if (row.status === 'failed') return 'error'
    if (row.status === 'warning') return 'warning'
    return undefined
  }

  // Map processor types to RouteNode types
  function toRouteNodeType(procType: string): RouteNode['type'] {
    switch (procType) {
      case 'consumer': return 'from'
      case 'transform': return 'process'
      case 'enrich': return 'process'
      default: return procType as RouteNode['type']
    }
  }

  // Build RouteFlow nodes from exchange processors
  const routeNodes: RouteNode[] = selectedExchange
    ? selectedExchange.processors.map((p) => ({
        name: p.name,
        type: toRouteNodeType(p.type),
        durationMs: p.durationMs,
        status: p.status,
      }))
    : []

  // Collect errors from processors
  const processorErrors = selectedExchange
    ? selectedExchange.processors.filter((p) => p.status === 'fail')
    : []
  const hasExchangeError = selectedExchange?.errorMessage != null
  const totalErrors = processorErrors.length + (hasExchangeError && processorErrors.length === 0 ? 1 : 0)

  return (
    <AppShell
      sidebar={
        <Sidebar apps={SIDEBAR_APPS} />
      }
      detail={
        selectedExchange ? (
          <DetailPanel
            open={panelOpen}
            onClose={() => setPanelOpen(false)}
            title={`${selectedExchange.orderId} — ${selectedExchange.route}`}
          >
            {/* Link to full detail page */}
            <div className={styles.panelSection}>
              <button
                className={styles.openDetailLink}
                onClick={() => navigate(`/exchanges/${selectedExchange.id}`)}
              >
                Open full details &#x2192;
              </button>
            </div>

            {/* Overview */}
            <div className={styles.panelSection}>
              <div className={styles.panelSectionTitle}>Overview</div>
              <div className={styles.overviewGrid}>
                <div className={styles.overviewRow}>
                  <span className={styles.overviewLabel}>Status</span>
                  <span className={styles.statusCell}>
                    <StatusDot variant={statusToVariant(selectedExchange.status)} />
                    <span>{statusLabel(selectedExchange.status)}</span>
                  </span>
                </div>
                <div className={styles.overviewRow}>
                  <span className={styles.overviewLabel}>Duration</span>
                  <MonoText size="sm">{formatDuration(selectedExchange.durationMs)}</MonoText>
                </div>
                <div className={styles.overviewRow}>
                  <span className={styles.overviewLabel}>Route</span>
                  <span>{selectedExchange.route}</span>
                </div>
                <div className={styles.overviewRow}>
                  <span className={styles.overviewLabel}>Customer</span>
                  <MonoText size="sm">{selectedExchange.customer}</MonoText>
                </div>
                <div className={styles.overviewRow}>
                  <span className={styles.overviewLabel}>Agent</span>
                  <MonoText size="sm">{selectedExchange.agent}</MonoText>
                </div>
                <div className={styles.overviewRow}>
                  <span className={styles.overviewLabel}>Correlation</span>
                  <MonoText size="xs">{selectedExchange.correlationId}</MonoText>
                </div>
                <div className={styles.overviewRow}>
                  <span className={styles.overviewLabel}>Timestamp</span>
                  <MonoText size="xs">{selectedExchange.timestamp.toISOString()}</MonoText>
                </div>
              </div>
            </div>

            {/* Errors */}
            {totalErrors > 0 && (
              <div className={styles.panelSection}>
                <div className={styles.panelSectionTitle}>
                  Errors
                  {totalErrors > 1 && (
                    <Badge label={`+${totalErrors - 1} more`} color="error" variant="outlined" />
                  )}
                </div>
                <div className={styles.errorBlock}>
                  <div className={styles.errorClass}>
                    {selectedExchange.errorClass ?? processorErrors[0]?.name}
                  </div>
                  <div className={styles.errorMessage}>
                    {selectedExchange.errorMessage ?? `Failed at processor: ${processorErrors[0]?.name}`}
                  </div>
                </div>
              </div>
            )}

            {/* Route Flow */}
            <div className={styles.panelSection}>
              <div className={styles.panelSectionTitle}>Route Flow</div>
              <RouteFlow nodes={routeNodes} />
            </div>

            {/* Processor Timeline */}
            <div className={styles.panelSection}>
              <div className={styles.panelSectionTitle}>
                Processor Timeline
                <span className={styles.panelSectionMeta}>{formatDuration(selectedExchange.durationMs)}</span>
              </div>
              <ProcessorTimeline
                processors={selectedExchange.processors}
                totalMs={selectedExchange.durationMs}
              />
            </div>
          </DetailPanel>
        ) : undefined
      }
    >
      {/* Top bar */}
      <TopBar
        breadcrumb={
          routeId
            ? [{ label: 'Applications', href: '/apps' }, { label: appId!, href: `/apps/${appId}` }, { label: routeId }]
            : appId
              ? [{ label: 'Applications', href: '/apps' }, { label: appId }]
              : [{ label: 'Applications' }]
        }
        environment="PRODUCTION"
        user={{ name: 'hendrik' }}
      />

      {/* Scrollable content */}
      <div className={styles.content}>

        {/* Health strip */}
        <div className={styles.healthStrip}>
          {kpiMetrics.map((kpi, i) => (
            <StatCard
              key={i}
              label={kpi.label}
              value={kpi.value}
              detail={kpi.detail}
              trend={kpi.trend}
              trendValue={kpi.trendValue}
              accent={kpi.accent}
              sparkline={kpi.sparkline}
            />
          ))}
        </div>

        {/* Exchanges table */}
        <div className={styles.tableSection}>
          <div className={styles.tableHeader}>
            <span className={styles.tableTitle}>Recent Exchanges</span>
            <div className={styles.tableRight}>
              <span className={styles.tableMeta}>
                {filteredExchanges.length.toLocaleString()} of {scopedExchanges.length.toLocaleString()} exchanges
              </span>
              <Badge label="LIVE" color="success" />
            </div>
          </div>

          <DataTable
            columns={COLUMNS}
            data={filteredExchanges}
            onRowClick={handleRowClick}
            selectedId={selectedId}
            sortable
            flush
            rowAccent={handleRowAccent}
            expandedContent={(row) =>
              row.errorMessage ? (
                <div className={styles.inlineError}>
                  <span className={styles.inlineErrorIcon}>⚠</span>
                  <div>
                    <div className={styles.inlineErrorText}>{row.errorMessage}</div>
                    <div className={styles.inlineErrorHint}>Click to view full stack trace</div>
                  </div>
                </div>
              ) : null
            }
          />
        </div>
      </div>

      {/* Shortcuts bar */}
      <ShortcutsBar shortcuts={SHORTCUTS} />
    </AppShell>
  )
}
