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

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

// Composites
import { ProcessorTimeline } from '../../design-system/composites/ProcessorTimeline/ProcessorTimeline'
import type { ProcessorStep } 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 { Badge } from '../../design-system/primitives/Badge/Badge'
import { StatusDot } from '../../design-system/primitives/StatusDot/StatusDot'
import { MonoText } from '../../design-system/primitives/MonoText/MonoText'
import { CodeBlock } from '../../design-system/primitives/CodeBlock/CodeBlock'
import { InfoCallout } from '../../design-system/primitives/InfoCallout/InfoCallout'

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

// Mock data
import { exchanges } from '../../mocks/exchanges'
import { buildRouteToAppMap } from '../../mocks/sidebar'

const ROUTE_TO_APP = buildRouteToAppMap()

// ─── Helpers ──────────────────────────────────────────────────────────────────
function statusToLabel(status: 'completed' | 'failed' | 'running' | 'warning'): string {
  switch (status) {
    case 'completed': return 'COMPLETED'
    case 'failed': return 'FAILED'
    case 'running': return 'RUNNING'
    case 'warning': return 'WARNING'
  }
}

// ─── Exchange body mock generators ──────────────────────────────────────────
function generateExchangeSnapshot(
  step: ProcessorStep,
  orderId: string,
  customer: string,
  stepIndex: number,
) {
  const baseBody = {
    orderId,
    customer,
    status: step.status === 'fail' ? 'ERROR' : 'PROCESSING',
    processorStep: step.name,
    stepIndex,
  }

  const headers: Record<string, string> = {
    'CamelCorrelationId': `cmr-${orderId.toLowerCase().replace('op-', '')}-${stepIndex}`,
    'Content-Type': 'application/json',
    'CamelTimerName': step.name,
    'CamelBreadcrumbId': `${orderId}-${stepIndex}`,
  }

  if (stepIndex === 0) {
    return {
      headers,
      body: JSON.stringify({
        ...baseBody,
        raw: { orderId, customer, items: ['ITEM-001', 'ITEM-002'], total: 142.50 },
      }, null, 2),
    }
  }

  if (step.type === 'enrich') {
    return {
      headers: {
        ...headers,
        'enrichedBy': step.name.replace('enrich(', '').replace(')', ''),
      },
      body: JSON.stringify({
        ...baseBody,
        enrichment: { source: step.name, addedFields: ['customerId', 'address', 'tier'] },
      }, null, 2),
    }
  }

  return {
    headers,
    body: JSON.stringify(baseBody, null, 2),
  }
}

function generateExchangeSnapshotOut(
  step: ProcessorStep,
  orderId: string,
  customer: string,
  stepIndex: number,
) {
  const statusResult = step.status === 'fail' ? 'ERROR' : step.status === 'slow' ? 'SLOW_OK' : 'OK'
  const baseBody = {
    orderId,
    customer,
    status: statusResult,
    processorStep: step.name,
    stepIndex,
    processed: true,
  }

  const headers: Record<string, string> = {
    'CamelCorrelationId': `cmr-${orderId.toLowerCase().replace('op-', '')}-${stepIndex}`,
    'Content-Type': 'application/json',
    'CamelTimerName': step.name,
    'CamelBreadcrumbId': `${orderId}-${stepIndex}`,
    'CamelProcessedAt': new Date().toISOString(),
  }

  if (step.type === 'enrich') {
    const source = step.name.replace('enrich(', '').replace(')', '')
    return {
      headers: {
        ...headers,
        'enrichedBy': source,
        'enrichmentComplete': 'true',
      },
      body: JSON.stringify({
        ...baseBody,
        enrichment: { source: step.name, addedFields: ['customerId', 'address', 'tier'], resolved: true },
      }, null, 2),
    }
  }

  return {
    headers,
    body: JSON.stringify(baseBody, null, 2),
  }
}

// ─── ExchangeDetail component ─────────────────────────────────────────────────
export function ExchangeDetail() {
  const { id } = useParams<{ id: string }>()
  const navigate = useNavigate()

  const exchange = useMemo(() => exchanges.find((e) => e.id === id), [id])

  // Find correlated exchanges, sorted by start time
  const correlatedExchanges = useMemo(() => {
    if (!exchange?.correlationGroup) return []
    return exchanges
      .filter((e) => e.correlationGroup === exchange.correlationGroup)
      .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime())
  }, [exchange])

  // Default selected processor: first failed, or 0
  const defaultIndex = useMemo(() => {
    if (!exchange) return 0
    const failIdx = exchange.processors.findIndex((p) => p.status === 'fail')
    return failIdx >= 0 ? failIdx : 0
  }, [exchange])

  const [selectedProcessorIndex, setSelectedProcessorIndex] = useState<number>(defaultIndex)
  const [timelineView, setTimelineView] = useState<'gantt' | 'flow'>('gantt')

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

  // Not found state
  if (!exchange) {
    return (
      <>
        <TopBar
          breadcrumb={[
            { label: 'Applications', href: '/apps' },
            { label: 'Exchanges' },
            { label: id ?? 'Unknown' },
          ]}
          environment="PRODUCTION"
          user={{ name: 'hendrik' }}
        />
        <div className={styles.content}>
          <InfoCallout variant="warning">Exchange "{id}" not found in mock data.</InfoCallout>
        </div>
      </>
    )
  }

  const statusVariant = statusToVariant(exchange.status)
  const statusLabel = statusToLabel(exchange.status)
  const selectedProc = exchange.processors[selectedProcessorIndex]
  const snapshotIn = selectedProc
    ? generateExchangeSnapshot(selectedProc, exchange.orderId, exchange.customer, selectedProcessorIndex)
    : null
  const snapshotOut = selectedProc
    ? generateExchangeSnapshotOut(selectedProc, exchange.orderId, exchange.customer, selectedProcessorIndex)
    : null
  const isSelectedFailed = selectedProc?.status === 'fail'

  return (
    <>
      {/* Top bar */}
      <TopBar
        breadcrumb={[
          { label: 'Applications', href: '/apps' },
          { label: exchange.route, href: `/apps/${ROUTE_TO_APP.get(exchange.route) ?? exchange.route}/${exchange.route}` },
          { label: exchange.id },
        ]}
        environment="PRODUCTION"
        user={{ name: 'hendrik' }}
      />

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

        {/* Exchange header card */}
        <div className={styles.exchangeHeader}>
          <div className={styles.headerRow}>
            <div className={styles.headerLeft}>
              <StatusDot variant={statusVariant} />
              <div>
                <div className={styles.exchangeId}>
                  <MonoText size="md">{exchange.id}</MonoText>
                  <Badge label={statusLabel} color={statusVariant} variant="filled" />
                </div>
                <div className={styles.exchangeRoute}>
                  Route: <span className={styles.routeLink} onClick={() => navigate(`/apps/${ROUTE_TO_APP.get(exchange.route) ?? exchange.route}/${exchange.route}`)}>{exchange.route}</span>
                  <span className={styles.headerDivider}>&middot;</span>
                  Order: <MonoText size="xs">{exchange.orderId}</MonoText>
                  <span className={styles.headerDivider}>&middot;</span>
                  Customer: <MonoText size="xs">{exchange.customer}</MonoText>
                </div>
              </div>
            </div>
            <div className={styles.headerRight}>
              <div className={styles.headerStat}>
                <div className={styles.headerStatLabel}>Duration</div>
                <div className={styles.headerStatValue}>{formatDuration(exchange.durationMs)}</div>
              </div>
              <div className={styles.headerStat}>
                <div className={styles.headerStatLabel}>Agent</div>
                <div className={styles.headerStatValue}>{exchange.agent}</div>
              </div>
              <div className={styles.headerStat}>
                <div className={styles.headerStatLabel}>Started</div>
                <div className={styles.headerStatValue}>
                  {exchange.timestamp.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
                </div>
              </div>
              <div className={styles.headerStat}>
                <div className={styles.headerStatLabel}>Processors</div>
                <div className={styles.headerStatValue}>{exchange.processors.length}</div>
              </div>
            </div>
          </div>

          {/* Correlation Chain */}
          {correlatedExchanges.length > 1 && (
            <div className={styles.correlationChain}>
              <span className={styles.chainLabel}>Correlated Exchanges</span>
              {correlatedExchanges.map((ce) => {
                const isCurrent = ce.id === exchange.id
                const variant = statusToVariant(ce.status)
                const statusCls =
                  variant === 'success' ? styles.chainNodeSuccess
                  : variant === 'error' ? styles.chainNodeError
                  : variant === 'running' ? styles.chainNodeRunning
                  : styles.chainNodeWarning
                return (
                  <button
                    key={ce.id}
                    className={`${styles.chainNode} ${statusCls} ${isCurrent ? styles.chainNodeCurrent : ''}`}
                    onClick={() => {
                      if (!isCurrent) navigate(`/exchanges/${ce.id}`)
                    }}
                    title={`${ce.id} — ${ce.route}`}
                  >
                    <StatusDot variant={variant} />
                    <span>{ce.route}</span>
                  </button>
                )
              })}
            </div>
          )}
        </div>

        {/* Processor Timeline Section */}
        <div className={styles.timelineSection}>
          <div className={styles.timelineHeader}>
            <span className={styles.timelineTitle}>
              Processor Timeline
              <span className={styles.procCount}>{exchange.processors.length} processors</span>
            </span>
            <div className={styles.timelineToggle}>
              <button
                className={`${styles.toggleBtn} ${timelineView === 'gantt' ? styles.toggleBtnActive : ''}`}
                onClick={() => setTimelineView('gantt')}
              >
                Timeline
              </button>
              <button
                className={`${styles.toggleBtn} ${timelineView === 'flow' ? styles.toggleBtnActive : ''}`}
                onClick={() => setTimelineView('flow')}
              >
                Flow
              </button>
            </div>
          </div>
          <div className={styles.timelineBody}>
            {timelineView === 'gantt' ? (
              <ProcessorTimeline
                processors={exchange.processors}
                totalMs={exchange.durationMs}
                onProcessorClick={(_proc, index) => setSelectedProcessorIndex(index)}
                selectedIndex={selectedProcessorIndex}
              />
            ) : (
              <RouteFlow
                nodes={routeNodes}
                onNodeClick={(_node, index) => setSelectedProcessorIndex(index)}
                selectedIndex={selectedProcessorIndex}
              />
            )}
          </div>
        </div>

        {/* Processor Detail Panel (split IN / OUT) */}
        {selectedProc && snapshotIn && snapshotOut && (
          <div className={styles.detailSplit}>
            {/* Message IN */}
            <div className={styles.detailPanel}>
              <div className={styles.panelHeader}>
                <span className={styles.panelTitle}>
                  <span className={styles.arrowIn}>&rarr;</span> Message IN
                </span>
                <span className={styles.panelTag}>at processor #{selectedProcessorIndex + 1} entry</span>
              </div>
              <div className={styles.panelBody}>
                <div className={styles.headersSection}>
                  <div className={styles.sectionLabel}>
                    Headers <span className={styles.count}>{Object.keys(snapshotIn.headers).length}</span>
                  </div>
                  <div className={styles.headerList}>
                    {Object.entries(snapshotIn.headers).map(([key, value]) => (
                      <div key={key} className={styles.headerKvRow}>
                        <span className={styles.headerKey}>{key}</span>
                        <span className={styles.headerValue}>{value}</span>
                      </div>
                    ))}
                  </div>
                </div>
                <div className={styles.bodySection}>
                  <div className={styles.sectionLabel}>Body</div>
                  <CodeBlock content={snapshotIn.body} language="json" copyable />
                </div>
              </div>
            </div>

            {/* Message OUT or Error */}
            {isSelectedFailed ? (
              <div className={`${styles.detailPanel} ${styles.detailPanelError}`}>
                <div className={styles.panelHeader}>
                  <span className={styles.panelTitle}>
                    <span className={styles.arrowError}>&times;</span> Error at Processor #{selectedProcessorIndex + 1}
                  </span>
                  <Badge label="FAILED" color="error" variant="filled" />
                </div>
                <div className={styles.panelBody}>
                  {exchange.errorClass && (
                    <div className={styles.errorBadgeRow}>
                      <span className={styles.errorHttpBadge}>{exchange.errorClass.split('.').pop()}</span>
                    </div>
                  )}
                  {exchange.errorMessage && (
                    <div className={styles.errorMessageBox}>{exchange.errorMessage}</div>
                  )}
                  <div className={styles.errorDetailGrid}>
                    <span className={styles.errorDetailLabel}>Error Class</span>
                    <span className={styles.errorDetailValue}>{exchange.errorClass ?? 'Unknown'}</span>
                    <span className={styles.errorDetailLabel}>Processor</span>
                    <span className={styles.errorDetailValue}>{selectedProc.name}</span>
                    <span className={styles.errorDetailLabel}>Duration</span>
                    <span className={styles.errorDetailValue}>{formatDuration(selectedProc.durationMs)}</span>
                    <span className={styles.errorDetailLabel}>Status</span>
                    <span className={styles.errorDetailValue}>{selectedProc.status.toUpperCase()}</span>
                  </div>
                </div>
              </div>
            ) : (
              <div className={styles.detailPanel}>
                <div className={styles.panelHeader}>
                  <span className={styles.panelTitle}>
                    <span className={styles.arrowOut}>&larr;</span> Message OUT
                  </span>
                  <span className={styles.panelTag}>after processor #{selectedProcessorIndex + 1}</span>
                </div>
                <div className={styles.panelBody}>
                  <div className={styles.headersSection}>
                    <div className={styles.sectionLabel}>
                      Headers <span className={styles.count}>{Object.keys(snapshotOut.headers).length}</span>
                    </div>
                    <div className={styles.headerList}>
                      {Object.entries(snapshotOut.headers).map(([key, value]) => (
                        <div key={key} className={styles.headerKvRow}>
                          <span className={styles.headerKey}>{key}</span>
                          <span className={styles.headerValue}>{value}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                  <div className={styles.bodySection}>
                    <div className={styles.sectionLabel}>Body</div>
                    <CodeBlock content={snapshotOut.body} language="json" copyable />
                  </div>
                </div>
              </div>
            )}
          </div>
        )}

      </div>
    </>
  )
}
