import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from "react";
import { getDataSource } from "../utils/queryUtils";
import type { BanOriginFilter, TimeRange } from "../types/ban";

interface DashboardFilterContextValue {
  /** Currently selected dashboard time-range preset. */
  timeRange: TimeRange;
  /** Currently selected dashboard origin filter. */
  originFilter: BanOriginFilter;
  /** Derived data source for the active time-range. */
  source: "fail2ban" | "archive";
  /** Update the selected time-range preset. */
  setTimeRange: (value: TimeRange) => void;
  /** Update the selected origin filter. */
  setOriginFilter: (value: BanOriginFilter) => void;
}

const DashboardFilterContext = createContext<DashboardFilterContextValue | null>(null);

const DEFAULT_FILTERS: DashboardFilterContextValue = {
  timeRange: "24h",
  originFilter: "all",
  source: "fail2ban",
  setTimeRange: (): void => {
    // no-op when no provider is present
  },
  setOriginFilter: (): void => {
    // no-op when no provider is present
  },
};

interface DashboardFilterProviderProps {
  children: ReactNode;
}

export function DashboardFilterProvider({ children }: DashboardFilterProviderProps): React.JSX.Element {
  const [timeRange, setTimeRange] = useState<TimeRange>(DEFAULT_FILTERS.timeRange);
  const [originFilter, setOriginFilter] = useState<BanOriginFilter>(DEFAULT_FILTERS.originFilter);

  const setTimeRangeCallback = useCallback((value: TimeRange): void => {
    setTimeRange(value);
  }, []);

  const setOriginFilterCallback = useCallback((value: BanOriginFilter): void => {
    setOriginFilter(value);
  }, []);

  const source = useMemo(() => getDataSource(timeRange), [timeRange]);

  const value = useMemo(
    () => ({
      timeRange,
      originFilter,
      source,
      setTimeRange: setTimeRangeCallback,
      setOriginFilter: setOriginFilterCallback,
    }),
    [timeRange, originFilter, source, setTimeRangeCallback, setOriginFilterCallback],
  );

  return <DashboardFilterContext.Provider value={value}>{children}</DashboardFilterContext.Provider>;
}

export function useDashboardFilters(): DashboardFilterContextValue {
  const context = useContext(DashboardFilterContext);
  return context ?? DEFAULT_FILTERS;
}
