import { useMemo, useState } from 'react';
import { DataTable, EmptyState, MonoText, SectionHeader, Toggle } from '@cameleer/design-system';
import type { Column } from '@cameleer/design-system';
import { LiveBanner } from './LiveBanner';
import { useApplicationConfig, useUpdateApplicationConfig } from '../../../../api/queries/commands';
import { useCatalog } from '../../../../api/queries/catalog';
import { applyRouteRecordingUpdate } from '../../../../utils/config-draft-utils';
import type { CatalogApp, CatalogRoute } from '../../../../api/queries/catalog';
import type { App } from '../../../../api/queries/admin/apps';
import type { Environment } from '../../../../api/queries/admin/environments';
import sectionStyles from '../../../../styles/section-card.module.css';
import appsStyles from '../../AppsTab.module.css';

interface RouteRecordingRow {
  id: string;
  routeId: string;
  recording: boolean;
}

interface Props {
  app: App;
  environment: Environment;
}

export function RouteRecordingTab({ app, environment }: Props) {
  const envSlug = environment.slug;
  const { data: agentConfig } = useApplicationConfig(app.slug, envSlug);
  const updateAgentConfig = useUpdateApplicationConfig();
  const { data: catalog } = useCatalog(envSlug);

  // Local draft — each toggle is immediately flushed to live agents
  const [recordingDraft, setRecordingDraft] = useState<Record<string, boolean> | null>(null);

  // Use draft if in-flight, otherwise reflect server state
  const effectiveRecording = recordingDraft ?? agentConfig?.routeRecording ?? {};

  const appRoutes: CatalogRoute[] = useMemo(() => {
    if (!catalog) return [];
    const entry = (catalog as CatalogApp[]).find((e) => e.slug === app.slug);
    return entry?.routes ?? [];
  }, [catalog, app.slug]);

  async function updateRouteRecording(routeId: string, recording: boolean) {
    if (!agentConfig) return;
    const next = applyRouteRecordingUpdate(effectiveRecording, routeId, recording);
    setRecordingDraft(next);
    try {
      await updateAgentConfig.mutateAsync({
        config: { ...agentConfig, routeRecording: next },
        environment: envSlug,
        apply: 'live',
      });
    } finally {
      setRecordingDraft(null);
    }
  }

  const routeRecordingRows: RouteRecordingRow[] = useMemo(
    () =>
      appRoutes.map((r) => ({
        id: r.routeId,
        routeId: r.routeId,
        recording: effectiveRecording[r.routeId] !== false,
      })),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [effectiveRecording, appRoutes],
  );

  const recordingCount = routeRecordingRows.filter((r) => r.recording).length;

  const routeRecordingColumns: Column<RouteRecordingRow>[] = useMemo(
    () => [
      {
        key: 'routeId',
        header: 'Route',
        render: (_v: unknown, row: RouteRecordingRow) => (
          <MonoText size="xs">{row.routeId}</MonoText>
        ),
      },
      {
        key: 'recording',
        header: 'Recording',
        width: '100px',
        render: (_v: unknown, row: RouteRecordingRow) => (
          <Toggle
            checked={row.recording}
            onChange={() => updateRouteRecording(row.routeId, !row.recording)}
            disabled={updateAgentConfig.isPending}
          />
        ),
      },
    ],
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [updateAgentConfig.isPending, effectiveRecording],
  );

  return (
    <div>
      <LiveBanner />
      <div className={sectionStyles.section}>
        <SectionHeader>Route Recording</SectionHeader>
        <span className={appsStyles.sectionSummary}>
          {recordingCount} of {routeRecordingRows.length} routes recording
        </span>
        {routeRecordingRows.length > 0 ? (
          <DataTable<RouteRecordingRow>
            columns={routeRecordingColumns}
            data={routeRecordingRows}
            pageSize={20}
            flush
          />
        ) : (
          <EmptyState
            title="No routes"
            description="No routes found for this application. Routes appear once agents report data."
          />
        )}
      </div>
    </div>
  );
}
