import { useMemo, useState } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import styles from './ExchangeDetail.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 { ProcessorTimeline } from '../../design-system/composites/ProcessorTimeline/ProcessorTimeline'
import type { ProcessorStep } from '../../design-system/composites/ProcessorTimeline/ProcessorTimeline'

// 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 { Collapsible } from '../../design-system/primitives/Collapsible/Collapsible'
import { CodeBlock } from '../../design-system/primitives/CodeBlock/CodeBlock'
import { InfoCallout } from '../../design-system/primitives/InfoCallout/InfoCallout'

// Mock data
import { exchanges } from '../../mocks/exchanges'
import { routes } from '../../mocks/routes'
import { agents } from '../../mocks/agents'

// ─── Sidebar data (shared) ────────────────────────────────────────────────────
const APPS = [
  { id: 'order-service', name: 'order-service', agentCount: 2, health: 'live' as const, exchangeCount: 1433 },
  { id: 'payment-svc', name: 'payment-svc', agentCount: 1, health: 'live' as const, exchangeCount: 912 },
  { id: 'shipment-tracker', name: 'shipment-tracker', agentCount: 2, health: 'live' as const, exchangeCount: 471 },
  { id: 'notification-hub', name: 'notification-hub', agentCount: 1, health: 'stale' as const, exchangeCount: 128 },
]

const SIDEBAR_ROUTES = routes.slice(0, 3).map((r) => ({
  id: r.id,
  name: r.name,
  exchangeCount: r.exchangeCount,
}))

// ─── 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 statusToVariant(status: 'completed' | 'failed' | 'running' | 'warning'): 'success' | 'error' | 'running' | 'warning' {
  switch (status) {
    case 'completed': return 'success'
    case 'failed': return 'error'
    case 'running': return 'running'
    case 'warning': return 'warning'
  }
}

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 generator ────────────────────────────────────────────
// For each processor step, generate a plausible exchange body snapshot
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-${Math.random().toString(36).slice(2, 10)}`,
    '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),
  }
}

// ─── ExchangeDetail component ─────────────────────────────────────────────────
export function ExchangeDetail() {
  const { id } = useParams<{ id: string }>()
  const navigate = useNavigate()
  const [activeItem, setActiveItem] = useState('')

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

  function handleItemClick(itemId: string) {
    setActiveItem(itemId)
    const route = routes.find((r) => r.id === itemId)
    if (route) navigate(`/routes/${itemId}`)
  }

  // Not found state
  if (!exchange) {
    return (
      <AppShell
        sidebar={
          <Sidebar
            apps={APPS}
            routes={SIDEBAR_ROUTES}
            agents={agents}
            activeItem={activeItem}
            onItemClick={handleItemClick}
          />
        }
      >
        <TopBar
          breadcrumb={[
            { label: 'Dashboard', href: '/' },
            { label: 'Exchanges' },
            { label: id ?? 'Unknown' },
          ]}
          environment="PRODUCTION"
          shift="Day (06:00-18:00)"
          user={{ name: 'hendrik' }}
        />
        <div className={styles.content}>
          <InfoCallout variant="warning">Exchange "{id}" not found in mock data.</InfoCallout>
        </div>
      </AppShell>
    )
  }

  const statusVariant = statusToVariant(exchange.status)
  const statusLabel = statusToLabel(exchange.status)

  return (
    <AppShell
      sidebar={
        <Sidebar
          apps={APPS}
          routes={SIDEBAR_ROUTES}
          agents={agents}
          activeItem={activeItem}
          onItemClick={handleItemClick}
        />
      }
    >
      {/* Top bar */}
      <TopBar
        breadcrumb={[
          { label: 'Dashboard', href: '/' },
          { label: exchange.route, href: `/routes/${exchange.route}` },
          { label: exchange.id },
        ]}
        environment="PRODUCTION"
        shift="Day (06:00-18:00)"
        user={{ name: 'hendrik' }}
      />

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

        {/* Exchange header */}
        <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(`/routes/${exchange.route}`)}>{exchange.route}</span>
                  <span className={styles.headerDivider}>·</span>
                  Order: <MonoText size="xs">{exchange.orderId}</MonoText>
                  <span className={styles.headerDivider}>·</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>
        </div>

        {/* Processor timeline */}
        <div className={styles.section}>
          <div className={styles.sectionHeader}>
            <span className={styles.sectionTitle}>Processor Timeline</span>
            <span className={styles.sectionMeta}>Total: {formatDuration(exchange.durationMs)}</span>
          </div>
          <div className={styles.timelineWrap}>
            <ProcessorTimeline
              processors={exchange.processors}
              totalMs={exchange.durationMs}
            />
          </div>
        </div>

        {/* Step-by-step inspector */}
        <div className={styles.section}>
          <div className={styles.sectionHeader}>
            <span className={styles.sectionTitle}>Exchange Inspector</span>
            <span className={styles.sectionMeta}>{exchange.processors.length} processor steps</span>
          </div>
          <div className={styles.inspectorSteps}>
            {exchange.processors.map((proc, index) => {
              const snapshot = generateExchangeSnapshot(proc, exchange.orderId, exchange.customer, index)
              const stepStatusClass =
                proc.status === 'fail'
                  ? styles.stepFail
                  : proc.status === 'slow'
                    ? styles.stepSlow
                    : styles.stepOk

              return (
                <Collapsible
                  key={index}
                  title={
                    <div className={styles.stepTitle}>
                      <span className={`${styles.stepIndex} ${stepStatusClass}`}>{index + 1}</span>
                      <span className={styles.stepName}>{proc.name}</span>
                      <Badge
                        label={proc.status.toUpperCase()}
                        color={proc.status === 'fail' ? 'error' : proc.status === 'slow' ? 'warning' : 'success'}
                        variant="outlined"
                      />
                      <span className={styles.stepDuration}>{formatDuration(proc.durationMs)}</span>
                    </div>
                  }
                  defaultOpen={proc.status === 'fail'}
                  className={styles.stepCollapsible}
                >
                  <div className={styles.stepBody}>
                    <div className={styles.stepPanel}>
                      <div className={styles.stepPanelLabel}>Exchange Headers</div>
                      <CodeBlock
                        content={JSON.stringify(snapshot.headers, null, 2)}
                        language="json"
                        copyable
                        className={styles.codeBlock}
                      />
                    </div>
                    <div className={styles.stepPanel}>
                      <div className={styles.stepPanelLabel}>Exchange Body</div>
                      <CodeBlock
                        content={snapshot.body}
                        language="json"
                        copyable
                        className={styles.codeBlock}
                      />
                    </div>
                  </div>
                </Collapsible>
              )
            })}
          </div>
        </div>

        {/* Error block (if failed) */}
        {exchange.status === 'failed' && exchange.errorMessage && (
          <div className={styles.errorSection}>
            <div className={styles.sectionHeader}>
              <span className={styles.sectionTitle}>Error Details</span>
              <Badge label="FAILED" color="error" />
            </div>
            <div className={styles.errorBody}>
              <div className={styles.errorClass}>{exchange.errorClass}</div>
              <pre className={styles.errorMessage}>{exchange.errorMessage}</pre>
              <div className={styles.errorHint}>
                Failed at processor: <MonoText size="xs">
                  {exchange.processors.find((p) => p.status === 'fail')?.name ?? 'unknown'}
                </MonoText>
              </div>
            </div>
          </div>
        )}

      </div>
    </AppShell>
  )
}
