import { useState, useMemo, useCallback } from 'react';
import { useParams, NavLink } from 'react-router';
import { useAgents } from '../../api/queries/agents';
import { useSearchExecutions, useExecutionStats, useStatsTimeseries } from '../../api/queries/executions';
import { StatCard } from '../../components/shared/StatCard';
import { ResultsTable } from '../executions/ResultsTable';
import { Pagination } from '../../components/shared/Pagination';
import { FilterChip } from '../../components/shared/FilterChip';
import type { SearchRequest } from '../../api/types';
import styles from './AppScopedView.module.css';

function todayMidnight(): string {
  const d = new Date();
  d.setHours(0, 0, 0, 0);
  const pad = (n: number) => n.toString().padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T00:00`;
}

function formatCompact(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 pctChange(current: number, previous: number): { text: string; direction: 'up' | 'down' | 'neutral' } {
  if (previous === 0) return { text: 'no prior data', direction: 'neutral' };
  const pct = ((current - previous) / previous) * 100;
  if (Math.abs(pct) < 0.5) return { text: '~0% vs yesterday', direction: 'neutral' };
  const arrow = pct > 0 ? '\u2191' : '\u2193';
  return { text: `${arrow} ${Math.abs(pct).toFixed(1)}% vs yesterday`, direction: pct > 0 ? 'up' : 'down' };
}

export function AppScopedView() {
  const { group } = useParams<{ group: string }>();
  const { data: agents } = useAgents();
  const [selectedRoute, setSelectedRoute] = useState<string | null>(null);
  const [status, setStatus] = useState<string[]>(['COMPLETED', 'FAILED']);
  const [live, setLive] = useState(true);
  const [offset, setOffset] = useState(0);
  const limit = 25;

  // Find agents belonging to this group
  const groupAgents = useMemo(() => {
    if (!agents || !group) return [];
    return agents.filter((a) => (a.group ?? 'default') === group);
  }, [agents, group]);

  const liveCount = groupAgents.filter((a) => a.status === 'LIVE').length;
  const staleCount = groupAgents.filter((a) => a.status === 'STALE').length;
  const deadCount = groupAgents.filter((a) => a.status === 'DEAD').length;

  // Collect unique routes from agents
  const routeIds = useMemo(() => {
    const set = new Set<string>();
    for (const a of groupAgents) {
      if (a.routeIds) for (const rid of a.routeIds) set.add(rid);
    }
    return Array.from(set).sort();
  }, [groupAgents]);

  // Build search request scoped to this group
  const timeFrom = todayMidnight();
  const timeFromIso = new Date(timeFrom).toISOString();

  const searchRequest: SearchRequest = useMemo(() => ({
    group: group || undefined,
    routeId: selectedRoute || undefined,
    status: status.length > 0 && status.length < 3 ? status.join(',') : undefined,
    timeFrom: timeFromIso,
    offset,
    limit,
    sortField: 'startTime',
    sortDir: 'desc',
  }), [group, selectedRoute, status, timeFromIso, offset, limit]);

  const { data, isLoading, isFetching } = useSearchExecutions(searchRequest, live);
  const { data: stats } = useExecutionStats(timeFromIso, undefined, selectedRoute || undefined, group);
  const { data: timeseries } = useStatsTimeseries(timeFromIso, undefined, selectedRoute || undefined, group);

  const sparkTotal = timeseries?.buckets.map((b) => b.totalCount) ?? [];
  const sparkFailed = timeseries?.buckets.map((b) => b.failedCount) ?? [];
  const sparkAvgDuration = timeseries?.buckets.map((b) => b.avgDurationMs) ?? [];
  const sparkP99 = timeseries?.buckets.map((b) => b.p99DurationMs) ?? [];
  const sparkActive = timeseries?.buckets.map((b) => b.activeCount) ?? [];

  const total = data?.total ?? 0;
  const results = data?.data ?? [];

  const failureRate = stats && stats.totalCount > 0
    ? (stats.failedCount / stats.totalCount) * 100 : 0;
  const prevFailureRate = stats && stats.prevTotalCount > 0
    ? (stats.prevFailedCount / stats.prevTotalCount) * 100 : 0;

  const avgChange = stats ? pctChange(stats.avgDurationMs, stats.prevAvgDurationMs) : null;
  const failRateChange = stats ? pctChange(failureRate, prevFailureRate) : null;
  const p99Change = stats ? pctChange(stats.p99LatencyMs, stats.prevP99LatencyMs) : null;

  const showFrom = total > 0 ? offset + 1 : 0;
  const showTo = Math.min(offset + limit, total);

  const toggleRoute = useCallback((rid: string) => {
    setSelectedRoute((prev) => prev === rid ? null : rid);
    setOffset(0);
  }, []);

  if (!group) {
    return <div className={styles.loading}>Missing group parameter</div>;
  }

  return (
    <>
      {/* Breadcrumb */}
      <nav className={styles.breadcrumb}>
        <NavLink to="/executions" className={styles.breadcrumbLink}>All</NavLink>
        <span className={styles.breadcrumbSep}>/</span>
        <span className={styles.breadcrumbCurrent}>{group}</span>
      </nav>

      {/* App Header */}
      <div className={styles.appHeader}>
        <div className={styles.appTitle}>{group}</div>
        <div className={styles.agentSummary}>
          {liveCount > 0 && <span className={styles.agentLive}>{liveCount} live</span>}
          {staleCount > 0 && <span className={styles.agentStale}>{staleCount} stale</span>}
          {deadCount > 0 && <span className={styles.agentDead}>{deadCount} dead</span>}
          {groupAgents.length === 0 && <span className={styles.agentDead}>no agents</span>}
        </div>
      </div>

      {/* Stats Bar */}
      <div className={styles.statsBar}>
        <StatCard label="Total Matches" value={total.toLocaleString()} accent="amber" change={stats ? `of ${formatCompact(stats.totalToday)} today` : 'from current search'} sparkData={sparkTotal} />
        <StatCard label="Avg Duration" value={stats ? `${stats.avgDurationMs.toLocaleString()}ms` : '--'} accent="cyan" change={avgChange?.text} changeDirection={avgChange?.direction} sparkData={sparkAvgDuration} />
        <StatCard label="Failure Rate" value={stats ? `${failureRate.toFixed(1)}%` : '--'} accent="rose" change={failRateChange?.text} changeDirection={failRateChange?.direction} sparkData={sparkFailed} />
        <StatCard label="P99 Latency" value={stats ? `${stats.p99LatencyMs.toLocaleString()}ms` : '--'} accent="green" change={p99Change?.text} changeDirection={p99Change?.direction} sparkData={sparkP99} />
        <StatCard label="In-Flight" value={stats ? stats.activeCount.toLocaleString() : '--'} accent="blue" change="running executions" sparkData={sparkActive} />
      </div>

      {/* Route Chips + Status Filters */}
      <div className={styles.filterBar}>
        <div className={styles.filterGroup}>
          <label className={styles.filterLabel}>Status</label>
          <FilterChip label="Completed" accent="green" active={status.includes('COMPLETED')} onClick={() => setStatus((s) => s.includes('COMPLETED') ? s.filter((x) => x !== 'COMPLETED') : [...s, 'COMPLETED'])} />
          <FilterChip label="Failed" accent="rose" active={status.includes('FAILED')} onClick={() => setStatus((s) => s.includes('FAILED') ? s.filter((x) => x !== 'FAILED') : [...s, 'FAILED'])} />
          <FilterChip label="Running" accent="blue" active={status.includes('RUNNING')} onClick={() => setStatus((s) => s.includes('RUNNING') ? s.filter((x) => x !== 'RUNNING') : [...s, 'RUNNING'])} />
        </div>
        <button className={`${styles.liveToggle} ${live ? styles.liveOn : styles.liveOff}`} onClick={() => setLive(!live)}>
          <span className={styles.liveDot} />
          {live ? 'LIVE' : 'PAUSED'}
        </button>
      </div>

      {/* Route Chips */}
      {routeIds.length > 0 && (
        <div className={styles.routeChips}>
          {routeIds.map((rid) => (
            <button
              key={rid}
              className={`${styles.routeChip} ${selectedRoute === rid ? styles.routeChipActive : ''}`}
              onClick={() => toggleRoute(rid)}
            >
              {rid}
            </button>
          ))}
        </div>
      )}

      {/* Results Header */}
      <div className={styles.resultsHeader}>
        <span className={styles.resultsCount}>
          Showing <strong>{showFrom}–{showTo}</strong> of <strong>{total.toLocaleString()}</strong> results
          {isFetching && !isLoading && ' · updating...'}
        </span>
      </div>

      {/* Results Table */}
      <ResultsTable results={results} loading={isLoading} />

      {/* Pagination */}
      <Pagination total={total} offset={offset} limit={limit} onChange={setOffset} />
    </>
  );
}
