import React, { useState, useMemo } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { TrendingUp, TrendingDown, ArrowRight, ExternalLink, AlertTriangle } from 'lucide-react'
import styles from './Dashboard.module.css'

// Layout
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'
import { KpiStrip } from '../../design-system/composites/KpiStrip/KpiStrip'
import type { KpiItem } from '../../design-system/composites/KpiStrip/KpiStrip'

// Primitives
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'

// Utils
import { formatDuration, statusToVariant, statusLabel, toRouteNodeType, durationClass } from '../../utils/format-utils'

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

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

// ─── KPI mapping ─────────────────────────────────────────────────────────────
const ACCENT_TO_COLOR: Record<KpiMetric['accent'], string> = {
  amber: 'var(--amber)',
  success: 'var(--success)',
  error: 'var(--error)',
  running: 'var(--running)',
  warning: 'var(--warning)',
}

const TREND_ICONS: Record<KpiMetric['trend'], React.ReactNode> = {
  up: <TrendingUp size={12} />,
  down: <TrendingDown size={12} />,
  neutral: <ArrowRight size={12} />,
}

function sentimentToVariant(sentiment: KpiMetric['trendSentiment']): 'success' | 'error' | 'muted' {
  switch (sentiment) {
    case 'good': return 'success'
    case 'bad': return 'error'
    case 'neutral': return 'muted'
  }
}

const kpiItems: KpiItem[] = kpiMetrics.map((m) => ({
  label: m.label,
  value: m.unit ? `${m.value} ${m.unit}` : m.value,
  trend: { label: <><span style={{ display: 'inline-flex', verticalAlign: 'middle' }}>{TREND_ICONS[m.trend]}</span> {m.trendValue}</>, variant: sentimentToVariant(m.trendSentiment) },
  subtitle: m.detail,
  sparkline: m.sparkline,
  borderColor: ACCENT_TO_COLOR[m.accent],
}))

// ─── Helpers ─────────────────────────────────────────────────────────────────
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}`
}

// ─── 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, styles)}>
        {formatDuration(row.durationMs)}
      </MonoText>
    ),
  },
  {
    key: 'agent',
    header: 'Agent',
    render: (_, row) => (
      <span className={styles.agentBadge}>
        <span className={styles.agentDot} />
        {row.agent}
      </span>
    ),
  },
]

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}`)
          }}
        >
          <ExternalLink size={14} />
        </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
  }

  // 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 (
    <>
      {/* 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 */}
        <KpiStrip items={kpiItems} />

        {/* 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
            fillHeight
            rowAccent={handleRowAccent}
            expandedContent={(row) =>
              row.errorMessage ? (
                <div className={styles.inlineError}>
                  <span className={styles.inlineErrorIcon}><AlertTriangle size={14} /></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} />

      {/* Detail panel (portals itself) */}
      {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 <ArrowRight size={14} style={{ verticalAlign: 'middle' }} />
            </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>
      )}
    </>
  )
}
