import { useState, useMemo } from 'react';
import { useParams, useNavigate, Link } from 'react-router';
import {
  Badge, StatusDot, DataTable, Tabs,
  AreaChart, LineChart, BarChart, RouteFlow, Spinner,
  MonoText,
} from '@cameleer/design-system';
import type { Column } from '@cameleer/design-system';
import { useGlobalFilters } from '@cameleer/design-system';
import { useRouteCatalog } from '../../api/queries/catalog';
import { useDiagramByRoute } from '../../api/queries/diagrams';
import { useProcessorMetrics } from '../../api/queries/processor-metrics';
import { useStatsTimeseries, useSearchExecutions } from '../../api/queries/executions';
import type { ExecutionSummary, AppCatalogEntry, RouteSummary } from '../../api/types';
import { mapDiagramToRouteNodes } from '../../utils/diagram-mapping';
import styles from './RouteDetail.module.css';

interface ExchangeRow extends ExecutionSummary {
  id: string;
}

interface ProcessorRow {
  id: string;
  processorId: string;
  callCount: number;
  avgDurationMs: number;
  p99DurationMs: number;
  errorCount: number;
}

interface ErrorPattern {
  message: string;
  count: number;
  lastSeen: string;
}

export default function RouteDetail() {
  const { appId, routeId } = useParams();
  const navigate = useNavigate();
  const { timeRange } = useGlobalFilters();
  const timeFrom = timeRange.start.toISOString();
  const timeTo = timeRange.end.toISOString();

  const [activeTab, setActiveTab] = useState('performance');

  const { data: catalog } = useRouteCatalog();
  const { data: diagram } = useDiagramByRoute(appId, routeId);
  const { data: processorMetrics, isLoading: processorLoading } = useProcessorMetrics(routeId ?? null, appId);
  const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, routeId, appId);
  const { data: recentResult, isLoading: recentLoading } = useSearchExecutions({
    timeFrom,
    timeTo,
    routeId: routeId || undefined,
    group: appId || undefined,
    offset: 0,
    limit: 50,
  });
  const { data: errorResult } = useSearchExecutions({
    timeFrom,
    timeTo,
    routeId: routeId || undefined,
    group: appId || undefined,
    status: 'FAILED',
    offset: 0,
    limit: 200,
  });

  const appEntry: AppCatalogEntry | undefined = useMemo(() =>
    (catalog || []).find((e: AppCatalogEntry) => e.appId === appId),
    [catalog, appId],
  );

  const routeSummary: RouteSummary | undefined = useMemo(() =>
    appEntry?.routes?.find((r: RouteSummary) => r.routeId === routeId),
    [appEntry, routeId],
  );

  const health = appEntry?.health ?? 'unknown';
  const exchangeCount = routeSummary?.exchangeCount ?? 0;
  const lastSeen = routeSummary?.lastSeen
    ? new Date(routeSummary.lastSeen).toLocaleString()
    : '—';

  const healthVariant = useMemo((): 'success' | 'warning' | 'error' | 'dead' => {
    const h = health.toLowerCase();
    if (h === 'healthy') return 'success';
    if (h === 'degraded') return 'warning';
    if (h === 'unhealthy') return 'error';
    return 'dead';
  }, [health]);

  const diagramNodes = useMemo(() => {
    if (!diagram?.nodes) return [];
    return mapDiagramToRouteNodes(diagram.nodes, []);
  }, [diagram]);

  const processorRows: ProcessorRow[] = useMemo(() =>
    (processorMetrics || []).map((p: any) => ({
      id: p.processorId,
      processorId: p.processorId,
      callCount: p.callCount ?? 0,
      avgDurationMs: p.avgDurationMs ?? 0,
      p99DurationMs: p.p99DurationMs ?? 0,
      errorCount: p.errorCount ?? 0,
    })),
    [processorMetrics],
  );

  const chartData = useMemo(() =>
    (timeseries?.buckets || []).map((b: any) => ({
      time: new Date(b.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
      throughput: b.totalCount,
      latency: b.avgDurationMs,
      errors: b.failedCount,
      successRate: b.totalCount > 0 ? ((b.totalCount - b.failedCount) / b.totalCount) * 100 : 100,
    })),
    [timeseries],
  );

  const exchangeRows: ExchangeRow[] = useMemo(() =>
    (recentResult?.data || []).map((e: ExecutionSummary) => ({ ...e, id: e.executionId })),
    [recentResult],
  );

  const errorPatterns: ErrorPattern[] = useMemo(() => {
    const failed = (errorResult?.data || []) as ExecutionSummary[];
    const grouped = new Map<string, { count: number; lastSeen: string }>();
    for (const ex of failed) {
      const msg = ex.errorMessage || 'Unknown error';
      const existing = grouped.get(msg);
      if (!existing) {
        grouped.set(msg, { count: 1, lastSeen: ex.startTime ?? '' });
      } else {
        existing.count += 1;
        if ((ex.startTime ?? '') > existing.lastSeen) {
          existing.lastSeen = ex.startTime ?? '';
        }
      }
    }
    return Array.from(grouped.entries())
      .map(([message, { count, lastSeen: ls }]) => ({
        message,
        count,
        lastSeen: ls ? new Date(ls).toLocaleString() : '—',
      }))
      .sort((a, b) => b.count - a.count);
  }, [errorResult]);

  const processorColumns: Column<ProcessorRow>[] = [
    { key: 'processorId', header: 'Processor', render: (v) => <MonoText size="sm">{String(v)}</MonoText> },
    { key: 'callCount', header: 'Calls', sortable: true },
    { key: 'avgDurationMs', header: 'Avg', sortable: true, render: (v) => `${(v as number).toFixed(1)}ms` },
    { key: 'p99DurationMs', header: 'P99', sortable: true, render: (v) => `${(v as number).toFixed(1)}ms` },
    { key: 'errorCount', header: 'Errors', sortable: true, render: (v) => {
      const n = v as number;
      return n > 0 ? <span style={{ color: 'var(--error)', fontWeight: 700 }}>{n}</span> : <span>0</span>;
    }},
  ];

  const exchangeColumns: Column<ExchangeRow>[] = [
    {
      key: 'status', header: 'Status', width: '80px',
      render: (v) => <StatusDot variant={v === 'COMPLETED' ? 'success' : v === 'FAILED' ? 'error' : 'running'} />,
    },
    { key: 'executionId', header: 'Exchange ID', render: (v) => <MonoText size="xs">{String(v).slice(0, 12)}</MonoText> },
    { key: 'startTime', header: 'Started', sortable: true, render: (v) => new Date(v as string).toLocaleTimeString() },
    { key: 'durationMs', header: 'Duration', sortable: true, render: (v) => `${v}ms` },
  ];

  const tabs = [
    { label: 'Performance', value: 'performance' },
    { label: 'Recent Executions', value: 'executions', count: exchangeRows.length },
    { label: 'Error Patterns', value: 'errors', count: errorPatterns.length },
  ];

  return (
    <div>
      <Link to={`/routes/${appId}`} className={styles.backLink}>
        ← {appId} routes
      </Link>

      <div className={styles.headerCard}>
        <div className={styles.headerRow}>
          <div className={styles.headerLeft}>
            <StatusDot variant={healthVariant} />
            <h2 style={{ margin: 0, fontSize: 18, fontWeight: 700 }}>{routeId}</h2>
            <Badge label={appId ?? ''} color="auto" />
          </div>
          <div className={styles.headerRight}>
            <div className={styles.headerStat}>
              <div className={styles.headerStatLabel}>Exchanges</div>
              <div className={styles.headerStatValue}>{exchangeCount.toLocaleString()}</div>
            </div>
            <div className={styles.headerStat}>
              <div className={styles.headerStatLabel}>Last Seen</div>
              <div className={styles.headerStatValue}>{lastSeen}</div>
            </div>
          </div>
        </div>
      </div>

      <div className={styles.diagramStatsGrid}>
        <div className={styles.diagramPane}>
          <div className={styles.paneTitle}>Route Diagram</div>
          {diagramNodes.length > 0 ? (
            <RouteFlow nodes={diagramNodes} />
          ) : (
            <div style={{ color: 'var(--text-muted)', fontSize: 13, padding: '8px 0' }}>
              No diagram available for this route.
            </div>
          )}
        </div>
        <div className={styles.statsPane}>
          <div className={styles.paneTitle}>Processor Stats</div>
          {processorLoading ? (
            <Spinner size="sm" />
          ) : processorRows.length > 0 ? (
            <DataTable columns={processorColumns} data={processorRows} sortable pageSize={10} />
          ) : (
            <div style={{ color: 'var(--text-muted)', fontSize: 13, padding: '8px 0' }}>
              No processor data available.
            </div>
          )}
        </div>
      </div>

      <div className={styles.tabSection}>
        <Tabs tabs={tabs} active={activeTab} onChange={setActiveTab} />

        {activeTab === 'performance' && (
          <div className={styles.chartGrid} style={{ marginTop: 16 }}>
            <div className={styles.chartCard}>
              <div className={styles.chartTitle}>Throughput</div>
              <AreaChart
                series={[{ label: 'Throughput', data: chartData.map((d, i) => ({ x: i, y: d.throughput })) }]}
                height={200}
              />
            </div>
            <div className={styles.chartCard}>
              <div className={styles.chartTitle}>Latency</div>
              <LineChart
                series={[{ label: 'Latency', data: chartData.map((d, i) => ({ x: i, y: d.latency })) }]}
                height={200}
              />
            </div>
            <div className={styles.chartCard}>
              <div className={styles.chartTitle}>Errors</div>
              <BarChart
                series={[{ label: 'Errors', data: chartData.map((d) => ({ x: d.time, y: d.errors })) }]}
                height={200}
              />
            </div>
            <div className={styles.chartCard}>
              <div className={styles.chartTitle}>Success Rate</div>
              <AreaChart
                series={[{ label: 'Success Rate', data: chartData.map((d, i) => ({ x: i, y: d.successRate })) }]}
                height={200}
              />
            </div>
          </div>
        )}

        {activeTab === 'executions' && (
          <div className={styles.executionsTable} style={{ marginTop: 16 }}>
            {recentLoading ? (
              <div style={{ padding: 24, display: 'flex', justifyContent: 'center' }}>
                <Spinner size="sm" />
              </div>
            ) : (
              <DataTable
                columns={exchangeColumns}
                data={exchangeRows}
                onRowClick={(row) => navigate(`/exchanges/${row.executionId}`)}
                sortable
                pageSize={20}
              />
            )}
          </div>
        )}

        {activeTab === 'errors' && (
          <div className={styles.errorPatterns} style={{ marginTop: 16 }}>
            {errorPatterns.length === 0 ? (
              <div style={{ color: 'var(--text-muted)', fontSize: 13, padding: '8px 0' }}>
                No error patterns found in the selected time range.
              </div>
            ) : (
              errorPatterns.map((ep, i) => (
                <div key={i} className={styles.errorRow}>
                  <span className={styles.errorMessage} title={ep.message}>{ep.message}</span>
                  <span className={styles.errorCount}>{ep.count}x</span>
                  <span className={styles.errorTime}>{ep.lastSeen}</span>
                </div>
              ))
            )}
          </div>
        )}
      </div>
    </div>
  );
}
