import { useMemo, useState } from 'react';
import { useParams, Link } from 'react-router';
import {
  StatCard, StatusDot, Badge, LineChart, AreaChart, BarChart,
  EventFeed, Spinner, EmptyState, SectionHeader, MonoText,
  LogViewer, Tabs, useGlobalFilters,
} from '@cameleer/design-system';
import type { FeedEvent, LogEntry } from '@cameleer/design-system';
import styles from './AgentInstance.module.css';
import { useAgents, useAgentEvents } from '../../api/queries/agents';
import { useStatsTimeseries } from '../../api/queries/executions';
import { useAgentMetrics } from '../../api/queries/agent-metrics';

const LOG_TABS = [
  { label: 'All', value: 'all' },
  { label: 'Warnings', value: 'warn' },
  { label: 'Errors', value: 'error' },
];

export default function AgentInstance() {
  const { appId, instanceId } = useParams();
  const { timeRange } = useGlobalFilters();
  const [logFilter, setLogFilter] = useState('all');
  const timeFrom = timeRange.start.toISOString();
  const timeTo = timeRange.end.toISOString();

  const { data: agents, isLoading } = useAgents(undefined, appId);
  const { data: events } = useAgentEvents(appId, instanceId);
  const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId);

  const agent = useMemo(
    () => (agents || []).find((a: any) => a.id === instanceId) as any,
    [agents, instanceId],
  );

  // Stat card metrics (latest 1 bucket)
  const { data: latestMetrics } = useAgentMetrics(
    agent?.id || null,
    ['jvm.cpu.process', 'jvm.memory.heap.used', 'jvm.memory.heap.max'],
    1,
  );
  const cpuPct = latestMetrics?.metrics?.['jvm.cpu.process']?.[0]?.value;
  const heapUsed = latestMetrics?.metrics?.['jvm.memory.heap.used']?.[0]?.value;
  const heapMax = latestMetrics?.metrics?.['jvm.memory.heap.max']?.[0]?.value;
  const memPct = heapMax ? (heapUsed! / heapMax) * 100 : undefined;

  // Chart metrics (60 buckets)
  const { data: jvmMetrics } = useAgentMetrics(
    agent?.id || null,
    ['jvm.cpu.process', 'jvm.memory.heap.used', 'jvm.memory.heap.max', 'jvm.threads.count', 'jvm.gc.time'],
    60,
  );

  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,
      })),
    [timeseries],
  );

  const feedEvents = useMemo<FeedEvent[]>(
    () =>
      (events || [])
        .filter((e: any) => !instanceId || e.agentId === instanceId)
        .map((e: any) => ({
          id: String(e.id),
          severity:
            e.eventType === 'WENT_DEAD'
              ? ('error' as const)
              : e.eventType === 'WENT_STALE'
                ? ('warning' as const)
                : e.eventType === 'RECOVERED'
                  ? ('success' as const)
                  : ('running' as const),
          message: `${e.eventType}${e.detail ? ' \u2014 ' + e.detail : ''}`,
          timestamp: new Date(e.timestamp),
        })),
    [events, instanceId],
  );

  // JVM chart series helpers
  const cpuSeries = useMemo(() => {
    const pts = jvmMetrics?.metrics?.['jvm.cpu.process'];
    if (!pts?.length) return null;
    return [{ label: 'CPU %', data: pts.map((p: any, i: number) => ({ x: i, y: p.value * 100 })) }];
  }, [jvmMetrics]);

  const heapSeries = useMemo(() => {
    const pts = jvmMetrics?.metrics?.['jvm.memory.heap.used'];
    if (!pts?.length) return null;
    return [{ label: 'Heap MB', data: pts.map((p: any, i: number) => ({ x: i, y: p.value / (1024 * 1024) })) }];
  }, [jvmMetrics]);

  const threadSeries = useMemo(() => {
    const pts = jvmMetrics?.metrics?.['jvm.threads.count'];
    if (!pts?.length) return null;
    return [{ label: 'Threads', data: pts.map((p: any, i: number) => ({ x: i, y: p.value })) }];
  }, [jvmMetrics]);

  const gcSeries = useMemo(() => {
    const pts = jvmMetrics?.metrics?.['jvm.gc.time'];
    if (!pts?.length) return null;
    return [{ label: 'GC ms', data: pts.map((p: any) => ({ x: String(p.time ?? ''), y: p.value })) }];
  }, [jvmMetrics]);

  const throughputSeries = useMemo(
    () =>
      chartData.length
        ? [{ label: 'Throughput', data: chartData.map((d: any, i: number) => ({ x: i, y: d.throughput })) }]
        : null,
    [chartData],
  );

  const errorSeries = useMemo(
    () =>
      chartData.length
        ? [{ label: 'Errors', data: chartData.map((d: any, i: number) => ({ x: i, y: d.errors })) }]
        : null,
    [chartData],
  );

  // Placeholder log entries (backend does not stream logs yet)
  const logEntries = useMemo<LogEntry[]>(() => [], []);
  const filteredLogs =
    logFilter === 'all' ? logEntries : logEntries.filter((l) => l.level === logFilter);

  if (isLoading) return <Spinner size="lg" />;

  const statusVariant =
    agent?.status === 'LIVE' ? 'live' : agent?.status === 'STALE' ? 'stale' : 'dead';
  const statusColor: 'success' | 'warning' | 'error' =
    agent?.status === 'LIVE' ? 'success' : agent?.status === 'STALE' ? 'warning' : 'error';
  const cpuDisplay = cpuPct != null ? (cpuPct * 100).toFixed(0) : null;
  const heapUsedMB = heapUsed != null ? (heapUsed / (1024 * 1024)).toFixed(0) : null;
  const heapMaxMB = heapMax != null ? (heapMax / (1024 * 1024)).toFixed(0) : null;

  return (
    <div className={styles.content}>
      {/* Stat strip — 5 columns */}
      <div className={styles.statStrip}>
        <StatCard
          label="CPU"
          value={cpuDisplay != null ? `${cpuDisplay}%` : '\u2014'}
          accent={
            cpuDisplay != null
              ? Number(cpuDisplay) > 85
                ? 'error'
                : Number(cpuDisplay) > 70
                  ? 'warning'
                  : 'success'
              : undefined
          }
        />
        <StatCard
          label="Memory"
          value={memPct != null ? `${memPct.toFixed(0)}%` : '\u2014'}
          accent={
            memPct != null
              ? memPct > 85
                ? 'error'
                : memPct > 70
                  ? 'warning'
                  : 'success'
              : undefined
          }
          detail={
            heapUsedMB != null && heapMaxMB != null
              ? `${heapUsedMB} MB / ${heapMaxMB} MB`
              : undefined
          }
        />
        <StatCard
          label="Throughput"
          value={agent?.tps != null ? `${agent.tps.toFixed(1)}/s` : '\u2014'}
          accent="amber"
          detail="msg/s"
        />
        <StatCard
          label="Errors"
          value={agent?.errorRate != null ? `${(agent.errorRate * 100).toFixed(1)}%` : '\u2014'}
          accent={agent?.errorRate > 0 ? 'error' : 'success'}
        />
        <StatCard
          label="Uptime"
          value={formatUptime(agent?.uptimeSeconds)}
          accent="running"
          detail={
            agent?.registeredAt
              ? `since ${new Date(agent.registeredAt).toLocaleDateString()}`
              : undefined
          }
        />
      </div>

      {/* Scope trail + badges */}
      {agent && (
        <>
          <div className={styles.scopeTrail}>
            <Link to="/agents" className={styles.scopeLink}>
              All Agents
            </Link>
            <span className={styles.scopeSep}>&#9656;</span>
            <Link to={`/agents/${appId}`} className={styles.scopeLink}>
              {appId}
            </Link>
            <span className={styles.scopeSep}>&#9656;</span>
            <span className={styles.scopeCurrent}>{agent.name}</span>
            <StatusDot variant={statusVariant} />
            <Badge label={agent.status} color={statusColor} />
            {agent.version && <Badge label={agent.version} variant="outlined" color="auto" />}
            <Badge
              label={`${agent.activeRoutes ?? (agent.routeIds?.length ?? 0)}/${agent.totalRoutes ?? (agent.routeIds?.length ?? 0)} routes`}
              color={
                (agent.activeRoutes ?? 0) < (agent.totalRoutes ?? 0) ? 'warning' : 'success'
              }
            />
          </div>

          {/* Process info card */}
          <div className={styles.processCard}>
            <SectionHeader>Process Information</SectionHeader>
            <div className={styles.processGrid}>
              {agent.capabilities?.jvmVersion && (
                <>
                  <span className={styles.processLabel}>JVM</span>
                  <MonoText size="xs">{agent.capabilities.jvmVersion}</MonoText>
                </>
              )}
              {agent.capabilities?.camelVersion && (
                <>
                  <span className={styles.processLabel}>Camel</span>
                  <MonoText size="xs">{agent.capabilities.camelVersion}</MonoText>
                </>
              )}
              {agent.capabilities?.springBootVersion && (
                <>
                  <span className={styles.processLabel}>Spring Boot</span>
                  <MonoText size="xs">{agent.capabilities.springBootVersion}</MonoText>
                </>
              )}
              <span className={styles.processLabel}>Started</span>
              <MonoText size="xs">
                {agent.registeredAt ? new Date(agent.registeredAt).toLocaleString() : '\u2014'}
              </MonoText>
              {agent.capabilities && (
                <>
                  <span className={styles.processLabel}>Capabilities</span>
                  <span className={styles.capTags}>
                    {Object.entries(agent.capabilities)
                      .filter(([, v]) => typeof v === 'boolean' && v)
                      .map(([k]) => (
                        <Badge key={k} label={k} variant="outlined" />
                      ))}
                  </span>
                </>
              )}
            </div>
          </div>

          {/* Routes */}
          {(agent.routeIds?.length ?? 0) > 0 && (
            <>
              <SectionHeader>Routes</SectionHeader>
              <div className={styles.routeBadges}>
                {(agent.routeIds || []).map((r: string) => (
                  <Badge key={r} label={r} color="auto" />
                ))}
              </div>
            </>
          )}
        </>
      )}

      {/* Charts grid — 3x2 */}
      <div className={styles.chartsGrid}>
        <div className={styles.chartCard}>
          <div className={styles.chartHeader}>
            <span className={styles.chartTitle}>CPU Usage</span>
            <span className={styles.chartMeta}>
              {cpuDisplay != null ? `${cpuDisplay}% current` : ''}
            </span>
          </div>
          {cpuSeries ? (
            <AreaChart
              series={cpuSeries}
              height={160}
              yLabel="%"
              threshold={{ value: 85, label: 'Alert' }}
            />
          ) : (
            <EmptyState title="No data" description="No CPU metrics available" />
          )}
        </div>

        <div className={styles.chartCard}>
          <div className={styles.chartHeader}>
            <span className={styles.chartTitle}>Memory (Heap)</span>
            <span className={styles.chartMeta}>
              {heapUsedMB != null && heapMaxMB != null
                ? `${heapUsedMB} MB / ${heapMaxMB} MB`
                : ''}
            </span>
          </div>
          {heapSeries ? (
            <AreaChart series={heapSeries} height={160} yLabel="MB" />
          ) : (
            <EmptyState title="No data" description="No heap metrics available" />
          )}
        </div>

        <div className={styles.chartCard}>
          <div className={styles.chartHeader}>
            <span className={styles.chartTitle}>Throughput</span>
            <span className={styles.chartMeta}>
              {agent?.tps != null ? `${agent.tps.toFixed(1)} msg/s` : ''}
            </span>
          </div>
          {throughputSeries ? (
            <LineChart series={throughputSeries} height={160} yLabel="msg/s" />
          ) : (
            <EmptyState title="No data" description="No throughput data in range" />
          )}
        </div>

        <div className={styles.chartCard}>
          <div className={styles.chartHeader}>
            <span className={styles.chartTitle}>Error Rate</span>
            <span className={styles.chartMeta}>
              {agent?.errorRate != null ? `${(agent.errorRate * 100).toFixed(1)}%` : ''}
            </span>
          </div>
          {errorSeries ? (
            <LineChart series={errorSeries} height={160} yLabel="err/h" />
          ) : (
            <EmptyState title="No data" description="No error data in range" />
          )}
        </div>

        <div className={styles.chartCard}>
          <div className={styles.chartHeader}>
            <span className={styles.chartTitle}>Thread Count</span>
            <span className={styles.chartMeta}>
              {threadSeries
                ? `${threadSeries[0].data[threadSeries[0].data.length - 1]?.y.toFixed(0)} active`
                : ''}
            </span>
          </div>
          {threadSeries ? (
            <LineChart series={threadSeries} height={160} yLabel="threads" />
          ) : (
            <EmptyState title="No data" description="No thread metrics available" />
          )}
        </div>

        <div className={styles.chartCard}>
          <div className={styles.chartHeader}>
            <span className={styles.chartTitle}>GC Pauses</span>
            <span className={styles.chartMeta} />
          </div>
          {gcSeries ? (
            <BarChart series={gcSeries} height={160} yLabel="ms" />
          ) : (
            <EmptyState title="No data" description="No GC metrics available" />
          )}
        </div>
      </div>

      {/* Log + Timeline side by side */}
      <div className={styles.bottomRow}>
        <div className={styles.logCard}>
          <div className={styles.logHeader}>
            <SectionHeader>Application Log</SectionHeader>
            <Tabs tabs={LOG_TABS} active={logFilter} onChange={setLogFilter} />
          </div>
          {filteredLogs.length > 0 ? (
            <LogViewer entries={filteredLogs} maxHeight={360} />
          ) : (
            <div className={styles.logEmpty}>
              Application log streaming is not yet available.
            </div>
          )}
        </div>

        <div className={styles.timelineCard}>
          <div className={styles.timelineHeader}>
            <span className={styles.chartTitle}>Timeline</span>
            <span className={styles.chartMeta}>{feedEvents.length} events</span>
          </div>
          {feedEvents.length > 0 ? (
            <EventFeed events={feedEvents} maxItems={50} />
          ) : (
            <div className={styles.logEmpty}>No events in the selected time range.</div>
          )}
        </div>
      </div>
    </div>
  );
}

function formatUptime(seconds?: number): string {
  if (!seconds) return '\u2014';
  const days = Math.floor(seconds / 86400);
  const hours = Math.floor((seconds % 86400) / 3600);
  const mins = Math.floor((seconds % 3600) / 60);
  if (days > 0) return `${days}d ${hours}h`;
  if (hours > 0) return `${hours}h ${mins}m`;
  return `${mins}m`;
}
