import { useMemo } from 'react';
import { useNavigate } from 'react-router';
import { GitBranch, Server, RotateCcw, FileText } from 'lucide-react';
import { StatusDot, MonoText, Badge, useGlobalFilters } from '@cameleer/design-system';
import { useCorrelationChain } from '../../api/queries/correlation';
import { useAgents } from '../../api/queries/agents';
import { useCatalog } from '../../api/queries/catalog';
import { useCanControl } from '../../auth/auth-store';
import { useEnvironmentStore } from '../../api/environment-store';
import type { ExecutionDetail } from '../../components/ExecutionDiagram/types';
import { attributeBadgeColor } from '../../utils/attribute-color';
import { formatDuration, statusLabel } from '../../utils/format-utils';
import { RouteControlBar } from './RouteControlBar';
import styles from './ExchangeHeader.module.css';

interface ExchangeHeaderProps {
  detail: ExecutionDetail;
  onCorrelatedSelect?: (executionId: string, applicationId: string, routeId: string) => void;
  onClearSelection?: () => void;
}

type StatusVariant = 'success' | 'error' | 'running' | 'warning';

function statusVariant(s: string): StatusVariant {
  switch (s) {
    case 'COMPLETED': return 'success';
    case 'FAILED': return 'error';
    case 'RUNNING': return 'running';
    default: return 'warning';
  }
}

export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }: ExchangeHeaderProps) {
  const navigate = useNavigate();
  const { timeRange } = useGlobalFilters();
  const storeEnv = useEnvironmentStore((s) => s.environment);
  // Prefer the exchange's own env over the selected env — correlated exchanges
  // always live in the same env as the one being viewed, and the user may have
  // switched env-picker after opening this detail.
  const environment = detail.environment ?? storeEnv;
  const { data: chainResult } = useCorrelationChain(detail.correlationId ?? null, environment);
  const chain = chainResult?.data;
  const showChain = chain && chain.length > 1;
  const attrs = Object.entries(detail.attributes ?? {});

  // Look up route state from catalog
  const { data: catalog } = useCatalog();
  const routeState = useMemo(() => {
    if (!catalog) return undefined;
    for (const app of catalog as any[]) {
      if (app.slug !== detail.applicationId) continue;
      for (const route of app.routes || []) {
        if (route.routeId === detail.routeId) {
          return (route.routeState ?? 'started') as 'started' | 'stopped' | 'suspended';
        }
      }
    }
    return undefined;
  }, [catalog, detail.applicationId, detail.routeId]);

  // Look up agent state for icon coloring + route control capability
  const { data: agents } = useAgents(undefined, detail.applicationId);
  const { agentState, hasRouteControl, hasReplay } = useMemo(() => {
    if (!agents) return { agentState: undefined, hasRouteControl: false, hasReplay: false };
    const agentList = agents as any[];
    const agent = detail.instanceId ? agentList.find((a: any) => a.instanceId === detail.instanceId) : undefined;
    return {
      agentState: agent?.status?.toLowerCase() as 'live' | 'stale' | 'dead' | undefined,
      hasRouteControl: agentList.some((a: any) => a.capabilities?.routeControl === true),
      hasReplay: agentList.some((a: any) => a.capabilities?.replay === true),
    };
  }, [agents, detail.instanceId]);

  const canControl = useCanControl();

  return (
    <div className={styles.header}>
      {/* Exchange info — always shown */}
      <div className={styles.info}>
        <StatusDot variant={statusVariant(detail.status)} />
        <Badge label={statusLabel(detail.status)} color={statusVariant(detail.status)} />
        {attrs.length > 0 && (
          <>
            <span className={styles.separator} />
            {attrs.map(([k, v]) => (
              <Badge key={k} label={`${k}: ${v}`} color={attributeBadgeColor(String(v))} />
            ))}
          </>
        )}
        <span className={styles.separator} />
        <button className={styles.linkBtn} onClick={() => { onClearSelection?.(); navigate(`/exchanges/${detail.applicationId}`); }} title="Show all exchanges for this application">
          <span className={styles.app}>{detail.applicationId}</span>
        </button>
        <button className={styles.linkBtn} onClick={() => { onClearSelection?.(); navigate(`/exchanges/${detail.applicationId}/${detail.routeId}`); }} title="Show all exchanges for this route">
          <span className={styles.route}>{detail.routeId}</span>
          <GitBranch size={12} className={styles.icon} />
        </button>
        {detail.instanceId && (
          <>
            <span className={styles.separator} />
            <button className={styles.linkBtn} onClick={() => navigate(`/runtime/${detail.applicationId}`)} title="All agents for this application">
              <span className={styles.app}>{detail.applicationId}</span>
            </button>
            <button className={styles.linkBtn} onClick={() => navigate(`/runtime/${detail.applicationId}/${detail.instanceId}`)} title="Agent details">
              <MonoText size="xs">{detail.instanceId}</MonoText>
              <Server size={12} className={agentState === 'live' ? styles.iconLive : agentState === 'stale' ? styles.iconStale : agentState === 'dead' ? styles.iconDead : styles.icon} />
            </button>
          </>
        )}
        <span className={styles.duration}>{formatDuration(detail.durationMs)}</span>
        <button
          className={styles.linkBtn}
          onClick={() => navigate(`/runtime/${detail.applicationId}`)}
          title="View surrounding logs"
        >
          <FileText size={12} className={styles.icon} />
        </button>
      </div>

      {/* Route control / replay — only if agent supports it AND user has operator+ role */}
      {canControl && (hasRouteControl || hasReplay) && (
        <RouteControlBar
          application={detail.applicationId}
          routeId={detail.routeId}
          routeState={routeState}
          hasRouteControl={hasRouteControl}
          hasReplay={hasReplay}
          agentId={detail.instanceId}
          exchangeId={detail.exchangeId}
          inputHeaders={detail.inputHeaders}
          inputBody={detail.inputBody}
        />
      )}

      {/* Correlation chain */}
      <div className={styles.chain}>
        <span className={styles.chainLabel}>Correlated</span>
        {showChain ? chain.map((ce: any, i: number) => {
            const isCurrent = ce.executionId === detail.executionId;
            const variant = statusVariant(ce.status);
            const isReplay = !!ce.isReplay;
            const statusCls =
              variant === 'success' ? styles.chainNodeSuccess
              : variant === 'error' ? styles.chainNodeError
              : variant === 'running' ? styles.chainNodeRunning
              : styles.chainNodeWarning;
            return (
              <span key={ce.executionId} className={styles.chainEntry}>
                {i > 0 && <span className={styles.chainArrow}>&rarr;</span>}
                <button
                  className={`${styles.chainNode} ${statusCls} ${isCurrent ? styles.chainNodeCurrent : ''}`}
                  onClick={() => {
                    if (!isCurrent && onCorrelatedSelect) {
                      onCorrelatedSelect(ce.executionId, ce.applicationId ?? detail.applicationId, ce.routeId);
                    }
                  }}
                  title={`${ce.executionId}\n${ce.routeId} \u2014 ${formatDuration(ce.durationMs)}${isReplay ? '\n(replay)' : ''}`}
                >
                  <StatusDot variant={variant} />
                  {isReplay && <RotateCcw size={9} className={styles.replayIcon} />}
                  <span className={styles.chainRoute}>{ce.routeId}</span>
                  <span className={styles.chainDuration}>{formatDuration(ce.durationMs)}</span>
                </button>
              </span>
            );
          }) : (
            <span className={styles.chainNone}>no correlated exchanges found</span>
          )}
        {showChain && (() => {
          const starts = chain.map((ce: any) => new Date(ce.startTime).getTime()).filter((t: number) => !isNaN(t));
          const ends = chain.map((ce: any) => new Date(ce.endTime ?? ce.startTime).getTime() + (ce.durationMs ?? 0)).filter((t: number) => !isNaN(t));
          const totalMs = starts.length > 0 && ends.length > 0 ? Math.max(...ends) - Math.min(...starts) : 0;
          return totalMs > 0 ? <span className={styles.chainTotal}>{formatDuration(totalMs)}</span> : null;
        })()}
      </div>
    </div>
  );
}
