import { useMemo } from 'react';
import { useGlobalFilters, Tooltip } from '@cameleer/design-system';
import { useExecutionStats } from '../api/queries/executions';
import type { Scope } from '../hooks/useScope';
import { formatPercent } from '../utils/format-utils';
import styles from './TabKpis.module.css';

interface TabKpisProps {
  scope: Scope;
}

function formatNum(n: number): string {
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
  if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;
  return n.toLocaleString();
}

function formatMs(ms: number): string {
  if (ms >= 60_000) return `${(ms / 1000).toFixed(0)}s`;
  if (ms >= 1000) return `${(ms / 1000).toFixed(1)}s`;
  return `${Math.round(ms)}ms`;
}

type Trend = 'up' | 'down' | 'flat';

function trend(current: number, previous: number): Trend {
  if (current > previous) return 'up';
  if (current < previous) return 'down';
  return 'flat';
}

function trendArrow(t: Trend): string {
  switch (t) {
    case 'up': return '\u2191';
    case 'down': return '\u2193';
    case 'flat': return '\u2192';
  }
}

function changePercent(current: number, previous: number): string | null {
  if (previous === 0 && current === 0) return null;
  if (previous === 0) return '+\u221e%';
  const pct = ((current - previous) / previous) * 100;
  const sign = pct > 0 ? '+' : '';
  return `${sign}${pct.toFixed(1)}%`;
}

/* ── Time period labels ───────────────────────────── */

function shortTime(d: Date): string {
  const h = String(d.getHours()).padStart(2, '0');
  const m = String(d.getMinutes()).padStart(2, '0');
  return `${h}:${m}`;
}

function shortDate(d: Date): string {
  const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  return `${months[d.getMonth()]} ${d.getDate()}`;
}

function formatRange(start: Date, end: Date): string {
  const sameDay = start.toDateString() === end.toDateString();
  if (sameDay) return `${shortDate(start)} ${shortTime(start)}\u2013${shortTime(end)}`;
  return `${shortDate(start)} ${shortTime(start)} \u2013 ${shortDate(end)} ${shortTime(end)}`;
}

function computePreviousPeriod(start: Date, end: Date): { label: string; prevLabel: string } {
  const durationMs = end.getTime() - start.getTime();
  const prevStart = new Date(start.getTime() - durationMs);
  const prevEnd = new Date(start.getTime());
  return {
    label: formatRange(start, end),
    prevLabel: formatRange(prevStart, prevEnd),
  };
}

/* ── Metric model ─────────────────────────────────── */

interface Metric {
  label: string;
  fullLabel: string;
  value: string;
  prevValue: string;
  change: string | null;
  trend: Trend;
  upIsBad?: boolean;
}

/* ── Tooltip ──────────────────────────────────────── */

function MetricTooltip({ m, currentLabel, prevLabel }: { m: Metric; currentLabel: string; prevLabel: string }) {
  const trendClass = m.trend === 'flat'
    ? styles.flat
    : (m.trend === 'up') === m.upIsBad
      ? styles.bad
      : styles.good;

  return (
    <div className={styles.tooltipBody}>
      <div className={styles.tooltipTitle}>{m.fullLabel}</div>

      <div className={styles.tooltipRows}>
        <div className={styles.tooltipRow}>
          <div className={styles.tooltipPeriod}>
            <span className={styles.tooltipDot} />
            <span className={styles.tooltipPeriodLabel}>Now</span>
            <span className={styles.tooltipTime}>{currentLabel}</span>
          </div>
          <span className={styles.tooltipValue}>{m.value}</span>
        </div>

        <div className={styles.tooltipRow}>
          <div className={styles.tooltipPeriod}>
            <span className={`${styles.tooltipDot} ${styles.tooltipDotPrev}`} />
            <span className={styles.tooltipPeriodLabel}>Prev</span>
            <span className={styles.tooltipTime}>{prevLabel}</span>
          </div>
          <span className={`${styles.tooltipValue} ${styles.tooltipValuePrev}`}>{m.prevValue}</span>
        </div>
      </div>

      {m.change && (
        <div className={`${styles.tooltipChange} ${trendClass}`}>
          {trendArrow(m.trend)} {m.change}
        </div>
      )}
    </div>
  );
}

/* ── Main component ───────────────────────────────── */

export function TabKpis({ scope }: TabKpisProps) {
  const { timeRange } = useGlobalFilters();
  const timeFrom = timeRange.start.toISOString();
  const timeTo = timeRange.end.toISOString();

  const { data: stats } = useExecutionStats(
    timeFrom, timeTo,
    scope.routeId, scope.appId,
  );

  const { label: currentLabel, prevLabel } = useMemo(
    () => computePreviousPeriod(timeRange.start, timeRange.end),
    [timeRange.start, timeRange.end],
  );

  const metrics: Metric[] = useMemo(() => {
    if (!stats) return [];

    const total = stats.totalCount ?? 0;
    const failed = stats.failedCount ?? 0;
    const prevTotal = stats.prevTotalCount ?? 0;
    const prevFailed = stats.prevFailedCount ?? 0;
    const errorRate = total > 0 ? (failed / total) * 100 : 0;
    const prevErrorRate = prevTotal > 0 ? (prevFailed / prevTotal) * 100 : 0;
    const avgMs = stats.avgDurationMs ?? 0;
    const prevAvgMs = stats.prevAvgDurationMs ?? 0;
    const p99 = stats.p99LatencyMs ?? 0;
    const prevP99 = stats.prevP99LatencyMs ?? 0;

    return [
      { label: 'Total', fullLabel: 'Total Exchanges', value: formatNum(total), prevValue: formatNum(prevTotal), change: changePercent(total, prevTotal), trend: trend(total, prevTotal) },
      { label: 'Err%', fullLabel: 'Error Rate', value: formatPercent(errorRate), prevValue: formatPercent(prevErrorRate), change: changePercent(errorRate, prevErrorRate), trend: trend(errorRate, prevErrorRate), upIsBad: true },
      { label: 'Avg', fullLabel: 'Avg Latency', value: formatMs(avgMs), prevValue: formatMs(prevAvgMs), change: changePercent(avgMs, prevAvgMs), trend: trend(avgMs, prevAvgMs), upIsBad: true },
      { label: 'P99', fullLabel: 'P99 Latency', value: formatMs(p99), prevValue: formatMs(prevP99), change: changePercent(p99, prevP99), trend: trend(p99, prevP99), upIsBad: true },
    ];
  }, [stats]);

  if (metrics.length === 0) return null;

  return (
    <div className={styles.kpis}>
      {metrics.map((m, i) => {
        const arrowClass = m.trend === 'flat'
          ? styles.flat
          : (m.trend === 'up') === m.upIsBad
            ? styles.bad
            : styles.good;
        const isNearEnd = i >= metrics.length - 2;

        return (
          <Tooltip
            key={m.label}
            content={<MetricTooltip m={m} currentLabel={currentLabel} prevLabel={prevLabel} />}
            position="bottom"
            className={`${styles.tooltipWrap} ${isNearEnd ? styles.tooltipEnd : ''}`}
          >
            <div className={styles.metric}>
              <span className={styles.label}>{m.label}</span>
              <span className={styles.value}>{m.value}</span>
              <span className={`${styles.arrow} ${arrowClass}`}>{trendArrow(m.trend)}</span>
            </div>
          </Tooltip>
        );
      })}
    </div>
  );
}
