import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { config } from '../../config';
import { useAuthStore } from '../../auth/auth-store';
import { useRefreshInterval } from './use-refresh-interval';

function authHeaders() {
  const token = useAuthStore.getState().accessToken;
  return {
    Authorization: `Bearer ${token}`,
    'X-Cameleer-Protocol-Version': '1',
  };
}

async function fetchJson<T>(path: string, params?: Record<string, string | undefined>): Promise<T> {
  const qs = new URLSearchParams();
  if (params) {
    for (const [k, v] of Object.entries(params)) {
      if (v != null) qs.set(k, v);
    }
  }
  const url = `${config.apiBaseUrl}${path}${qs.toString() ? `?${qs}` : ''}`;
  const res = await fetch(url, { headers: authHeaders() });
  if (!res.ok) throw new Error(`Failed to fetch ${path}`);
  return res.json();
}

// ── Timeseries by app (L1 charts) ─────────────────────────────────────

export interface TimeseriesBucket {
  time: string;
  totalCount: number;
  failedCount: number;
  avgDurationMs: number;
  p99DurationMs: number;
  activeCount: number;
}

export interface GroupedTimeseries {
  [key: string]: { buckets: TimeseriesBucket[] };
}

export function useTimeseriesByApp(from?: string, to?: string, environment?: string) {
  const refetchInterval = useRefreshInterval(30_000);
  return useQuery({
    queryKey: ['dashboard', 'timeseries-by-app', environment, from, to],
    queryFn: () => fetchJson<GroupedTimeseries>(
      `/environments/${encodeURIComponent(environment!)}/stats/timeseries/by-app`, {
      from, to, buckets: '24',
    }),
    enabled: !!from && !!environment,
    placeholderData: (prev: GroupedTimeseries | undefined) => prev,
    refetchInterval,
  });
}

// ── Timeseries by route (L2 charts) ───────────────────────────────────

export function useTimeseriesByRoute(from?: string, to?: string, application?: string, environment?: string) {
  const refetchInterval = useRefreshInterval(30_000);
  return useQuery({
    queryKey: ['dashboard', 'timeseries-by-route', environment, from, to, application],
    queryFn: () => fetchJson<GroupedTimeseries>(
      `/environments/${encodeURIComponent(environment!)}/stats/timeseries/by-route`, {
      from, to, application, buckets: '24',
    }),
    enabled: !!from && !!application && !!environment,
    placeholderData: (prev: GroupedTimeseries | undefined) => prev,
    refetchInterval,
  });
}

// ── Top errors (L2/L3) ────────────────────────────────────────────────

export interface TopError {
  errorType: string;
  routeId: string | null;
  processorId: string | null;
  count: number;
  velocity: number;
  trend: 'accelerating' | 'stable' | 'decelerating';
  lastSeen: string;
}

export function useTopErrors(from?: string, to?: string, application?: string, routeId?: string, environment?: string) {
  const refetchInterval = useRefreshInterval(10_000);
  return useQuery({
    queryKey: ['dashboard', 'top-errors', environment, from, to, application, routeId],
    queryFn: () => fetchJson<TopError[]>(
      `/environments/${encodeURIComponent(environment!)}/errors/top`, {
      from, to, application, routeId, limit: '5',
    }),
    enabled: !!from && !!environment,
    placeholderData: (prev: TopError[] | undefined) => prev,
    refetchInterval,
  });
}

// ── Punchcard (weekday x hour heatmap, rolling 7 days) ────────────────

export interface PunchcardCell {
  weekday: number;
  hour: number;
  totalCount: number;
  failedCount: number;
}

export function usePunchcard(application?: string, environment?: string) {
  const refetchInterval = useRefreshInterval(60_000);
  return useQuery({
    queryKey: ['dashboard', 'punchcard', environment, application],
    queryFn: () => fetchJson<PunchcardCell[]>(
      `/environments/${encodeURIComponent(environment!)}/stats/punchcard`, { application }),
    enabled: !!environment,
    placeholderData: (prev: PunchcardCell[] | undefined) => prev ?? [],
    refetchInterval,
  });
}

// ── App settings ──────────────────────────────────────────────────────

export interface AppSettings {
  appId: string;
  environment: string;
  slaThresholdMs: number;
  healthErrorWarn: number;
  healthErrorCrit: number;
  healthSlaWarn: number;
  healthSlaCrit: number;
  createdAt: string;
  updatedAt: string;
}

export function useAppSettings(appId?: string, environment?: string) {
  return useQuery({
    queryKey: ['app-settings', environment, appId],
    queryFn: () => fetchJson<AppSettings>(
      `/environments/${encodeURIComponent(environment!)}/apps/${encodeURIComponent(appId!)}/settings`),
    enabled: !!appId && !!environment,
    staleTime: 60_000,
  });
}

export function useAllAppSettings(environment?: string) {
  return useQuery({
    queryKey: ['app-settings', 'all', environment],
    queryFn: () => fetchJson<AppSettings[]>(
      `/environments/${encodeURIComponent(environment!)}/app-settings`),
    enabled: !!environment,
    staleTime: 60_000,
  });
}

export function useUpdateAppSettings() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async ({ appId, environment, settings }:
        { appId: string; environment: string; settings: Omit<AppSettings, 'appId' | 'createdAt' | 'updatedAt'> }) => {
      const res = await fetch(
        `${config.apiBaseUrl}/environments/${encodeURIComponent(environment)}/apps/${encodeURIComponent(appId)}/settings`,
        {
          method: 'PUT',
          headers: { ...authHeaders(), 'Content-Type': 'application/json' },
          body: JSON.stringify(settings),
        });
      if (!res.ok) throw new Error('Failed to update app settings');
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['app-settings'] });
    },
  });
}
