"use client";

import { createContext, useContext, useEffect, useMemo, useState } from "react";

import {
  timelineCopy as defaultTimelineCopy,
  timelineDateActions as defaultTimelineDateActions,
  timelineStatusOptions as defaultTimelineStatusOptions,
  type TimelineDateAction,
  type TimelineStatusFilter
} from "../timeline/timeline-ui-config";

type TimelineCopy = typeof defaultTimelineCopy;
type TimelineCopyPatch = Partial<Omit<TimelineCopy, "filters" | "summary">> & {
  filters?: Partial<TimelineCopy["filters"]>;
  summary?: Partial<TimelineCopy["summary"]>;
};

export type RuntimeUiConfig = {
  timeline?: {
    copy?: TimelineCopyPatch;
    dateActions?: Array<Partial<TimelineDateAction> & { key: string }>;
    statusOptions?: Array<{ value: TimelineStatusFilter; label: string }>;
  };
};

type TimelineDateActionPatch = Array<Partial<TimelineDateAction> & { key: string }>;

type RuntimeUiConfigContextValue = {
  timelineCopy: TimelineCopy;
  timelineDateActions: TimelineDateAction[];
  timelineStatusOptions: Array<{ value: TimelineStatusFilter; label: string }>;
};

const mergeTimelineCopy = (patch?: TimelineCopyPatch): TimelineCopy => ({
  ...defaultTimelineCopy,
  ...patch,
  filters: {
    ...defaultTimelineCopy.filters,
    ...patch?.filters
  },
  summary: {
    ...defaultTimelineCopy.summary,
    ...patch?.summary
  }
});

const mergeDateActions = (patches?: TimelineDateActionPatch) => {
  if (!patches || patches.length === 0) {
    return defaultTimelineDateActions;
  }

  const patchesByKey = new Map(patches.map((patch) => [patch.key, patch]));

  return defaultTimelineDateActions.map((action) => ({
    ...action,
    ...patchesByKey.get(action.key)
  }));
};

const createRuntimeValue = (config: RuntimeUiConfig | null): RuntimeUiConfigContextValue => ({
  timelineCopy: mergeTimelineCopy(config?.timeline?.copy),
  timelineDateActions: mergeDateActions(config?.timeline?.dateActions),
  timelineStatusOptions:
    config?.timeline?.statusOptions && config.timeline.statusOptions.length > 0
      ? config.timeline.statusOptions
      : defaultTimelineStatusOptions
});

const RuntimeUiConfigContext = createContext<RuntimeUiConfigContextValue>(createRuntimeValue(null));

export const RuntimeUiConfigProvider = ({
  children,
  initialConfig
}: {
  children: React.ReactNode;
  initialConfig?: RuntimeUiConfig | null;
}) => {
  const [runtimeConfig, setRuntimeConfig] = useState<RuntimeUiConfig | null>(initialConfig ?? null);

  useEffect(() => {
    let cancelled = false;

    fetch("/runtime/ui-config.json", { cache: "no-store" })
      .then((response) => (response.ok ? response.json() : null))
      .then((config: RuntimeUiConfig | null) => {
        if (!cancelled && config) {
          setRuntimeConfig(config);
        }
      })
      .catch(() => undefined);

    return () => {
      cancelled = true;
    };
  }, []);

  const value = useMemo(() => createRuntimeValue(runtimeConfig), [runtimeConfig]);

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

export const useRuntimeUiConfig = () => useContext(RuntimeUiConfigContext);
