import { useMemo } from 'react';
import { useParams, useNavigate } from 'react-router';
import {
  KpiStrip,
  DataTable,
  ThemedChart,
  Area,
  Line,
  ReferenceLine,
  CHART_COLORS,
  Card,
  Sparkline,
  MonoText,
  Badge,
} from '@cameleer/design-system';
import type { KpiItem, Column } from '@cameleer/design-system';
import { useGlobalFilters } from '@cameleer/design-system';
import { useRouteMetrics } from '../../api/queries/catalog';
import { useExecutionStats, useStatsTimeseries } from '../../api/queries/executions';
import {
  useTimeseriesByRoute,
  useTopErrors,
  useAppSettings,
  usePunchcard,
} from '../../api/queries/dashboard';
import { useEnvironmentStore } from '../../api/environment-store';
import type { TopError } from '../../api/queries/dashboard';
import { Treemap } from './Treemap';
import type { TreemapItem } from './Treemap';
import { PunchcardHeatmap } from './PunchcardHeatmap';
import type { RouteMetrics } from '../../api/types';
import {
  trendArrow,
  trendIndicator,
  formatThroughput,
  formatSlaCompliance,
  formatRelativeTime,
} from './dashboard-utils';
import styles from './DashboardTab.module.css';
import tableStyles from '../../styles/table-section.module.css';
import refreshStyles from '../../styles/refresh-indicator.module.css';
import rateStyles from '../../styles/rate-colors.module.css';

// ── Route table row type ────────────────────────────────────────────────────

interface RouteRow {
  id: string;
  routeId: string;
  exchangeCount: number;
  successRate: number;
  avgDurationMs: number;
  p99DurationMs: number;
  slaCompliance: number;
  sparkline: number[];
}

// ── Route performance columns ───────────────────────────────────────────────

const ROUTE_COLUMNS: Column<RouteRow>[] = [
  {
    key: 'routeId',
    header: 'Route ID',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm">{row.routeId}</MonoText>
    ),
  },
  {
    key: 'exchangeCount',
    header: 'Throughput',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm">{row.exchangeCount.toLocaleString()}</MonoText>
    ),
  },
  {
    key: 'successRate',
    header: 'Success%',
    sortable: true,
    render: (_, row) => {
      const pct = row.successRate * 100;
      const cls = pct >= 99 ? rateStyles.rateGood : pct >= 97 ? rateStyles.rateWarn : rateStyles.rateBad;
      return <MonoText size="sm" className={cls}>{pct.toFixed(1)}%</MonoText>;
    },
  },
  {
    key: 'avgDurationMs',
    header: 'Avg(ms)',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm">{Math.round(row.avgDurationMs)}</MonoText>
    ),
  },
  {
    key: 'p99DurationMs',
    header: 'P99(ms)',
    sortable: true,
    render: (_, row) => {
      const cls = row.p99DurationMs > 300 ? rateStyles.rateBad : row.p99DurationMs > 200 ? rateStyles.rateWarn : rateStyles.rateGood;
      return <MonoText size="sm" className={cls}>{Math.round(row.p99DurationMs)}</MonoText>;
    },
  },
  {
    key: 'slaCompliance',
    header: 'SLA%',
    sortable: true,
    render: (_, row) => {
      const cls = row.slaCompliance >= 99 ? rateStyles.rateGood : row.slaCompliance >= 95 ? rateStyles.rateWarn : rateStyles.rateBad;
      return <MonoText size="sm" className={cls}>{formatSlaCompliance(row.slaCompliance)}</MonoText>;
    },
  },
  {
    key: 'sparkline',
    header: 'Sparkline',
    render: (_, row) => (
      <Sparkline data={row.sparkline} width={80} height={24} />
    ),
  },
];

// ── Top errors columns ──────────────────────────────────────────────────────

type ErrorRow = TopError & { id: string };

const ERROR_COLUMNS: Column<ErrorRow>[] = [
  {
    key: 'errorType',
    header: 'Error Type',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm">{row.errorType}</MonoText>
    ),
  },
  {
    key: 'routeId',
    header: 'Route',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm">{row.routeId ?? '\u2014'}</MonoText>
    ),
  },
  {
    key: 'count',
    header: 'Count',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm">{row.count.toLocaleString()}</MonoText>
    ),
  },
  {
    key: 'velocity',
    header: 'Velocity',
    sortable: true,
    render: (_, row) => {
      const arrow = trendArrow(row.trend);
      const cls = row.trend === 'accelerating' ? rateStyles.rateBad
        : row.trend === 'decelerating' ? rateStyles.rateGood
        : rateStyles.rateNeutral;
      return <MonoText size="sm" className={cls}>{row.velocity.toFixed(1)}/min {arrow}</MonoText>;
    },
  },
  {
    key: 'lastSeen',
    header: 'Last Seen',
    sortable: true,
    render: (_, row) => (
      <MonoText size="sm">{formatRelativeTime(row.lastSeen)}</MonoText>
    ),
  },
];

// ── Build KPI items ─────────────────────────────────────────────────────────

function buildKpiItems(
  stats: {
    totalCount: number;
    failedCount: number;
    p99LatencyMs: number;
    prevTotalCount: number;
    prevFailedCount: number;
    prevP99LatencyMs: number;
  } | undefined,
  slaThresholdMs: number,
  throughputSparkline: number[],
  latencySparkline: number[],
  errors: TopError[] | undefined,
  windowSeconds: number,
): KpiItem[] {
  const totalCount = stats?.totalCount ?? 0;
  const failedCount = stats?.failedCount ?? 0;
  const prevTotalCount = stats?.prevTotalCount ?? 0;
  const prevFailedCount = stats?.prevFailedCount ?? 0;
  const p99Ms = stats?.p99LatencyMs ?? 0;
  const prevP99Ms = stats?.prevP99LatencyMs ?? 0;

  // Throughput
  const throughputTrend = trendIndicator(totalCount, prevTotalCount);

  // Success Rate
  const successRate = totalCount > 0 ? ((totalCount - failedCount) / totalCount) * 100 : 100;
  const prevSuccessRate = prevTotalCount > 0 ? ((prevTotalCount - prevFailedCount) / prevTotalCount) * 100 : 100;
  const successTrend = trendIndicator(successRate, prevSuccessRate);

  // P99 Latency
  const latencyTrend = trendIndicator(p99Ms, prevP99Ms);

  // SLA Compliance — percentage of exchanges under threshold
  // Approximate from p99: if p99 < threshold, ~99%+ are compliant
  const slaCompliance = p99Ms <= slaThresholdMs ? 99.9 : Math.max(0, 100 - ((p99Ms - slaThresholdMs) / slaThresholdMs) * 10);

  // Error Velocity — aggregate from top errors
  const errorList = errors ?? [];
  const totalVelocity = errorList.reduce((sum, e) => sum + e.velocity, 0);
  const hasAccelerating = errorList.some((e) => e.trend === 'accelerating');
  const allDecelerating = errorList.length > 0 && errorList.every((e) => e.trend === 'decelerating');
  const velocityTrendLabel = hasAccelerating ? '\u25B2' : allDecelerating ? '\u25BC' : '\u2500\u2500';
  const velocityVariant = hasAccelerating ? 'error' as const : allDecelerating ? 'success' as const : 'muted' as const;

  return [
    {
      label: 'Throughput',
      value: formatThroughput(totalCount, windowSeconds),
      trend: {
        label: throughputTrend.label,
        variant: throughputTrend.direction === 'up' ? 'success' as const : throughputTrend.direction === 'down' ? 'error' as const : 'muted' as const,
      },
      sparkline: throughputSparkline,
      borderColor: 'var(--amber)',
    },
    {
      label: 'Success Rate',
      value: `${successRate.toFixed(2)}%`,
      trend: {
        label: successTrend.label,
        variant: successTrend.direction === 'up' ? 'success' as const : successTrend.direction === 'down' ? 'error' as const : 'muted' as const,
      },
      borderColor: successRate >= 99 ? 'var(--success)' : successRate >= 95 ? 'var(--warning)' : 'var(--error)',
    },
    {
      label: 'P99 Latency',
      value: `${Math.round(p99Ms)}ms`,
      trend: {
        label: latencyTrend.label,
        variant: latencyTrend.direction === 'up' ? 'error' as const : latencyTrend.direction === 'down' ? 'success' as const : 'muted' as const,
      },
      sparkline: latencySparkline,
      borderColor: p99Ms > slaThresholdMs ? 'var(--error)' : 'var(--success)',
    },
    {
      label: 'SLA Compliance',
      value: formatSlaCompliance(slaCompliance),
      trend: {
        label: slaCompliance >= 99 ? 'OK' : 'BREACH',
        variant: slaCompliance >= 99 ? 'success' as const : 'error' as const,
      },
      subtitle: `Threshold: ${slaThresholdMs}ms`,
      borderColor: slaCompliance >= 99 ? 'var(--success)' : slaCompliance >= 95 ? 'var(--warning)' : 'var(--error)',
    },
    {
      label: 'Error Velocity',
      value: `${totalVelocity.toFixed(1)}/min`,
      trend: {
        label: velocityTrendLabel,
        variant: velocityVariant,
      },
      subtitle: `${errorList.length} error type${errorList.length !== 1 ? 's' : ''} tracked`,
      borderColor: hasAccelerating ? 'var(--error)' : allDecelerating ? 'var(--success)' : 'var(--text-muted)',
    },
  ];
}

// ── Component ───────────────────────────────────────────────────────────────

export default function DashboardL2() {
  const { appId } = useParams<{ appId: string }>();
  const navigate = useNavigate();
  const selectedEnv = useEnvironmentStore((s) => s.environment);
  const { timeRange } = useGlobalFilters();
  const timeFrom = timeRange.start.toISOString();
  const timeTo = timeRange.end.toISOString();
  const windowSeconds = (timeRange.end.getTime() - timeRange.start.getTime()) / 1000;

  // Data hooks
  const { data: stats } = useExecutionStats(timeFrom, timeTo, undefined, appId, selectedEnv);
  const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId, selectedEnv);
  const { data: metrics } = useRouteMetrics(timeFrom, timeTo, appId, selectedEnv);
  const { data: timeseriesByRoute } = useTimeseriesByRoute(timeFrom, timeTo, appId, selectedEnv);
  const { data: errors } = useTopErrors(timeFrom, timeTo, appId, undefined, selectedEnv);
  const { data: punchcardData } = usePunchcard(appId, selectedEnv);
  const { data: appSettings } = useAppSettings(appId, selectedEnv);

  const slaThresholdMs = appSettings?.slaThresholdMs ?? 300;

  // Route performance table rows
  const routeRows: RouteRow[] = useMemo(() =>
    (metrics || []).map((m: RouteMetrics) => ({
      id: m.routeId,
      routeId: m.routeId,
      exchangeCount: m.exchangeCount,
      successRate: m.successRate,
      avgDurationMs: m.avgDurationMs,
      p99DurationMs: m.p99DurationMs,
      slaCompliance: m.slaCompliance ?? -1,
      sparkline: m.sparkline ?? [],
    })),
    [metrics],
  );

  // Treemap items: one per route, sized by exchange count, colored by SLA
  const treemapItems: TreemapItem[] = useMemo(
    () => routeRows.map(r => ({
      id: r.routeId, label: r.routeId,
      value: r.exchangeCount,
      slaCompliance: r.slaCompliance >= 0 ? r.slaCompliance : 100,
    })),
    [routeRows],
  );

  // KPI sparklines from timeseries
  const throughputSparkline = useMemo(() =>
    (timeseries?.buckets || []).map((b) => b.totalCount),
    [timeseries],
  );
  const latencySparkline = useMemo(() =>
    (timeseries?.buckets || []).map((b) => b.p99DurationMs),
    [timeseries],
  );

  const kpiItems = useMemo(() =>
    buildKpiItems(stats, slaThresholdMs, throughputSparkline, latencySparkline, errors, windowSeconds),
    [stats, slaThresholdMs, throughputSparkline, latencySparkline, errors, windowSeconds],
  );

  // Throughput by Route — flat data for ThemedChart
  const throughputByRouteData = useMemo(() => {
    if (!timeseriesByRoute) return { data: [], keys: [] as string[] };
    const entries = Object.entries(timeseriesByRoute);
    if (!entries.length) return { data: [], keys: [] as string[] };
    const len = entries[0][1].buckets.length;
    const keys = entries.map(([routeId]) => routeId);
    const data = Array.from({ length: len }, (_, i) => {
      const point: Record<string, number | string> = { idx: i };
      for (const [routeId, { buckets }] of entries) {
        point[routeId] = buckets[i]?.totalCount ?? 0;
      }
      return point;
    });
    return { data, keys };
  }, [timeseriesByRoute]);

  // Latency percentiles chart — flat data for ThemedChart
  const latencyChartData = useMemo(() => {
    const buckets = timeseries?.buckets || [];
    return buckets.map((b, i) => ({
      idx: i,
      p99: b.p99DurationMs,
      avg: b.avgDurationMs,
    }));
  }, [timeseries]);

  // Error rows with stable identity
  const errorRows = useMemo(() =>
    (errors ?? []).map((e, i) => ({ ...e, id: `${e.errorType}-${e.routeId}-${i}` })),
    [errors],
  );

  return (
    <div className={styles.content}>
      <div className={refreshStyles.refreshIndicator}>
        <span className={refreshStyles.refreshDot} />
        <span className={refreshStyles.refreshText}>Auto-refresh: 30s</span>
      </div>

      {/* KPI Strip */}
      <KpiStrip items={kpiItems} />

      {/* Route Performance Table */}
      <div className={tableStyles.tableSection}>
        <div className={tableStyles.tableHeader}>
          <span className={tableStyles.tableTitle}>Route Performance</span>
          <div className={tableStyles.tableRight}>
            <span className={tableStyles.tableMeta}>{routeRows.length} routes</span>
            <Badge label="AUTO" color="success" />
          </div>
        </div>
        <DataTable
          columns={ROUTE_COLUMNS}
          data={routeRows}
          sortable
          onRowClick={(row) => navigate(`/dashboard/${appId}/${row.routeId}`)}
        />
      </div>

      {/* Charts: Throughput by Route + Latency Percentiles */}
      {(timeseries?.buckets?.length ?? 0) > 0 && (
        <div className={styles.chartGrid}>
          <Card title="Throughput by Route">
            <ThemedChart data={throughputByRouteData.data} height={200} xDataKey="idx" yLabel="msg/s">
              {throughputByRouteData.keys.map((key, i) => (
                <Area key={key} dataKey={key} name={key} stroke={CHART_COLORS[i % CHART_COLORS.length]}
                  fill={CHART_COLORS[i % CHART_COLORS.length]} fillOpacity={0.1} strokeWidth={2} dot={false} />
              ))}
            </ThemedChart>
          </Card>

          <Card title="Latency Percentiles">
            <ThemedChart data={latencyChartData} height={200} xDataKey="idx" yLabel="ms">
              <Line dataKey="p99" name="P99" stroke={CHART_COLORS[0]} strokeWidth={2} dot={false} />
              <Line dataKey="avg" name="Avg" stroke={CHART_COLORS[1]} strokeWidth={2} dot={false} />
              <ReferenceLine y={slaThresholdMs} stroke="var(--error)" strokeDasharray="5 3"
                label={{ value: `SLA ${slaThresholdMs}ms`, position: 'right', fill: 'var(--error)', fontSize: 9 }} />
            </ThemedChart>
          </Card>
        </div>
      )}

      {/* Top 5 Errors — hidden when empty */}
      {errorRows.length > 0 && (
        <div className={tableStyles.tableSection}>
          <div className={tableStyles.tableHeader}>
            <span className={tableStyles.tableTitle}>Top Errors</span>
            <span className={tableStyles.tableMeta}>{errorRows.length} error types</span>
          </div>
          <DataTable
            columns={ERROR_COLUMNS}
            data={errorRows}
            sortable
          />
        </div>
      )}

      {/* Treemap + Punchcard heatmaps side by side */}
      {treemapItems.length > 0 && (
        <div className={styles.vizRow}>
          <Card title="Route Volume vs SLA Compliance">
            <Treemap
              items={treemapItems}
              onItemClick={(id) => navigate(`/dashboard/${appId}/${id}`)}
            />
          </Card>
          <Card title="7-Day Pattern">
            <PunchcardHeatmap cells={punchcardData ?? []} />
          </Card>
        </div>
      )}
    </div>
  );
}
