import React, { useState, useMemo } from 'react';
import { useParams, useNavigate } from 'react-router';
import {
  Badge, StatusDot, MonoText, CodeBlock, InfoCallout,
  ProcessorTimeline, Breadcrumb, Spinner, RouteFlow,
} from '@cameleer/design-system';
import { useExecutionDetail, useProcessorSnapshot } from '../../api/queries/executions';
import { useCorrelationChain } from '../../api/queries/correlation';
import { useDiagramByRoute } from '../../api/queries/diagrams';
import { mapDiagramToRouteNodes } from '../../utils/diagram-mapping';
import styles from './ExchangeDetail.module.css';

function countProcessors(nodes: any[]): number {
  return nodes.reduce((sum, n) => sum + 1 + countProcessors(n.children || []), 0);
}

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 parseHeaders(raw: string | undefined | null): Record<string, string> {
  if (!raw) return {};
  try {
    const parsed = JSON.parse(raw);
    if (typeof parsed === 'object' && parsed !== null) {
      const result: Record<string, string> = {};
      for (const [k, v] of Object.entries(parsed)) {
        result[k] = typeof v === 'string' ? v : JSON.stringify(v);
      }
      return result;
    }
  } catch { /* ignore */ }
  return {};
}

export default function ExchangeDetail() {
  const { id } = useParams();
  const navigate = useNavigate();
  const { data: detail, isLoading } = useExecutionDetail(id ?? null);
  const [timelineView, setTimelineView] = useState<'gantt' | 'flow'>('gantt');
  const { data: correlationData } = useCorrelationChain(detail?.correlationId ?? null);
  const { data: diagram } = useDiagramByRoute(detail?.groupName, detail?.routeId);

  const procList = detail ? (detail.processors?.length ? detail.processors : (detail.children ?? [])) : [];

  // Auto-select first failed processor, or 0
  const defaultIndex = useMemo(() => {
    if (!procList.length) return 0;
    const failIdx = procList.findIndex((p: any) =>
      (p.status || '').toUpperCase() === 'FAILED' || p.status === 'fail'
    );
    return failIdx >= 0 ? failIdx : 0;
  }, [procList]);

  const [selectedProcessorIndex, setSelectedProcessorIndex] = useState<number | null>(null);
  const activeIndex = selectedProcessorIndex ?? defaultIndex;

  const { data: snapshot } = useProcessorSnapshot(id ?? null, procList.length > 0 ? activeIndex : null);

  const processors = useMemo(() => {
    if (!procList.length) return [];
    const result: any[] = [];
    let offset = 0;
    function walk(node: any) {
      result.push({
        name: node.processorId || node.processorType,
        type: node.processorType,
        durationMs: node.durationMs ?? 0,
        status: node.status === 'COMPLETED' ? 'ok' : node.status === 'FAILED' ? 'fail' : 'ok',
        startMs: offset,
      });
      offset += node.durationMs ?? 0;
      if (node.children) node.children.forEach(walk);
    }
    procList.forEach(walk);
    return result;
  }, [procList]);

  const selectedProc = processors[activeIndex];
  const isSelectedFailed = selectedProc?.status === 'fail';

  // Parse snapshot headers
  const inputHeaders = parseHeaders(snapshot?.inputHeaders);
  const outputHeaders = parseHeaders(snapshot?.outputHeaders);
  const inputBody = snapshot?.inputBody ?? null;
  const outputBody = snapshot?.outputBody ?? null;

  if (isLoading) return <div style={{ display: 'flex', justifyContent: 'center', padding: '4rem' }}><Spinner size="lg" /></div>;
  if (!detail) return <InfoCallout variant="warning">Exchange not found</InfoCallout>;

  return (
    <div>
      <Breadcrumb items={[
        { label: 'Dashboard', href: '/apps' },
        { label: detail.groupName || 'App', href: `/apps/${detail.groupName}` },
        { label: id?.slice(0, 12) || '' },
      ]} />

      {/* Exchange header card */}
      <div className={styles.exchangeHeader}>
        <div className={styles.headerRow}>
          <div className={styles.headerLeft}>
            <StatusDot variant={detail.status === 'COMPLETED' ? 'success' : detail.status === 'FAILED' ? 'error' : 'running'} />
            <div>
              <div className={styles.exchangeId}>
                <MonoText size="md">{id}</MonoText>
                <Badge label={detail.status} color={detail.status === 'COMPLETED' ? 'success' : 'error'} variant="filled" />
              </div>
              <div className={styles.exchangeRoute}>
                Route: <span className={styles.routeLink} onClick={() => navigate(`/apps/${detail.groupName}/${detail.routeId}`)}>{detail.routeId}</span>
                {detail.groupName && (
                  <>
                    <span className={styles.headerDivider}>&middot;</span>
                    App: <MonoText size="xs">{detail.groupName}</MonoText>
                  </>
                )}
              </div>
            </div>
          </div>
          <div className={styles.headerRight}>
            <div className={styles.headerStat}>
              <div className={styles.headerStatLabel}>Duration</div>
              <div className={styles.headerStatValue}>{formatDuration(detail.durationMs)}</div>
            </div>
            <div className={styles.headerStat}>
              <div className={styles.headerStatLabel}>Agent</div>
              <div className={styles.headerStatValue}>{detail.agentId}</div>
            </div>
            <div className={styles.headerStat}>
              <div className={styles.headerStatLabel}>Started</div>
              <div className={styles.headerStatValue}>
                {detail.startTime ? new Date(detail.startTime).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}>{countProcessors(procList)}</div>
            </div>
          </div>
        </div>

        {/* Correlation Chain */}
        {correlationData?.data && correlationData.data.length > 1 && (
          <div className={styles.correlationChain}>
            <span className={styles.chainLabel}>Correlated Exchanges</span>
            {correlationData.data.map((exec: any) => {
              const isCurrent = exec.executionId === id;
              const variant = exec.status === 'COMPLETED' ? 'success' : exec.status === 'FAILED' ? 'error' : 'running';
              const statusCls =
                variant === 'success' ? styles.chainNodeSuccess
                : variant === 'error' ? styles.chainNodeError
                : styles.chainNodeRunning;
              return (
                <button
                  key={exec.executionId}
                  className={`${styles.chainNode} ${statusCls} ${isCurrent ? styles.chainNodeCurrent : ''}`}
                  onClick={() => { if (!isCurrent) navigate(`/exchanges/${exec.executionId}`); }}
                  title={`${exec.executionId} — ${exec.routeId}`}
                >
                  <StatusDot variant={variant as any} />
                  <span>{exec.routeId}</span>
                </button>
              );
            })}
            {correlationData.total > 20 && (
              <span className={styles.chainMore}>+{correlationData.total - 20} more</span>
            )}
          </div>
        )}
      </div>

      {/* Error callout */}
      {detail.errorMessage && (
        <InfoCallout variant="error">
          {detail.errorMessage}
        </InfoCallout>
      )}

      {/* Processor Timeline / Flow Section */}
      <div className={styles.timelineSection}>
        <div className={styles.timelineHeader}>
          <span className={styles.timelineTitle}>
            Processor Timeline
            <span className={styles.procCount}>{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' ? (
            processors.length > 0 ? (
              <ProcessorTimeline
                processors={processors}
                totalMs={detail.durationMs}
                onProcessorClick={(_p, i) => setSelectedProcessorIndex(i)}
                selectedIndex={activeIndex}
              />
            ) : (
              <InfoCallout>No processor data available</InfoCallout>
            )
          ) : (
            diagram ? (
              <RouteFlow
                nodes={mapDiagramToRouteNodes(diagram.nodes || [], procList)}
                onNodeClick={(_node, i) => setSelectedProcessorIndex(i)}
                selectedIndex={activeIndex}
              />
            ) : (
              <Spinner />
            )
          )}
        </div>
      </div>

      {/* Processor Detail: Message IN / Message OUT or Error */}
      {selectedProc && snapshot && (
        <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 #{activeIndex + 1} entry</span>
            </div>
            <div className={styles.panelBody}>
              {Object.keys(inputHeaders).length > 0 && (
                <div className={styles.headersSection}>
                  <div className={styles.sectionLabel}>
                    Headers <span className={styles.count}>{Object.keys(inputHeaders).length}</span>
                  </div>
                  <div className={styles.headerList}>
                    {Object.entries(inputHeaders).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={inputBody ?? 'null'} />
              </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 #{activeIndex + 1}
                </span>
                <Badge label="FAILED" color="error" variant="filled" />
              </div>
              <div className={styles.panelBody}>
                {detail.errorMessage && (
                  <div className={styles.errorMessageBox}>{detail.errorMessage}</div>
                )}
                <div className={styles.errorDetailGrid}>
                  <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 #{activeIndex + 1}</span>
              </div>
              <div className={styles.panelBody}>
                {Object.keys(outputHeaders).length > 0 && (
                  <div className={styles.headersSection}>
                    <div className={styles.sectionLabel}>
                      Headers <span className={styles.count}>{Object.keys(outputHeaders).length}</span>
                    </div>
                    <div className={styles.headerList}>
                      {Object.entries(outputHeaders).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={outputBody ?? 'null'} />
                </div>
              </div>
            </div>
          )}
        </div>
      )}

      {/* No snapshot loaded yet - show prompt */}
      {selectedProc && !snapshot && procList.length > 0 && (
        <div style={{ color: 'var(--text-muted)', fontSize: 12, textAlign: 'center', padding: 20 }}>
          Loading exchange snapshot...
        </div>
      )}
    </div>
  );
}
