"use client";

import React, {
  createContext,
  useContext,
  useEffect,
  useState,
  ReactNode,
} from "react";
import { getManagerMemberships } from "@/app/utils/api/user-dashboard-platform/mappingFunction";
import { getAllUsers } from "@/app/utils/api/user-dashboard-platform";
import type {
  RoleMembership,
  User,
} from "@/app/utils/api/user-dashboard-platform/type";
import { getAllFXRate } from "@/app/utils/api/fxRate";
import type { FxRateResponse } from "@/app/utils/api/fxRate/type";

/** year -> currency (upper-cased) -> rate */
export type FxRateMap = Map<string, Map<string, number>>;

type SelectOption = { value: string; label: string };

interface AppCacheState {
  /** userId -> userName */
  userNameMap: Map<string, string>;
  /** userId -> designation */
  userDesignationMap: Map<string, string | null>;
  /** all active (non-deleted) platform users */
  activeUsers: User[];
  /** year -> currency -> rate, derived from the raw FX response */
  fxRateMap: FxRateMap;
  /** the raw FX rate response (paginated) */
  fxRateResponse: FxRateResponse | null;
  /** userId/userName options for users holding the Project Manager role */
  projectManagerOptions: SelectOption[];
  /** userId/userName options for users holding the Account Manager role */
  accountManagerOptions: SelectOption[];
  isLoading: boolean;
  refresh: () => void;
}

const AppCacheContext = createContext<AppCacheState>({
  userNameMap: new Map(),
  userDesignationMap: new Map(),
  activeUsers: [],
  fxRateMap: new Map(),
  fxRateResponse: null,
  projectManagerOptions: [],
  accountManagerOptions: [],
  isLoading: true,
  refresh: () => {},
});

export function AppCacheProvider({ children }: { children: ReactNode }) {
  const [userNameMap, setUserNameMap] = useState<Map<string, string>>(new Map());
  const [userDesignationMap, setUserDesignationMap] = useState<
    Map<string, string | null>
  >(new Map());
  const [activeUsers, setActiveUsers] = useState<User[]>([]);
  const [fxRateMap, setFxRateMap] = useState<FxRateMap>(new Map());
  const [fxRateResponse, setFxRateResponse] = useState<FxRateResponse | null>(
    null,
  );
  const [projectManagerOptions, setProjectManagerOptions] = useState<
    SelectOption[]
  >([]);
  const [accountManagerOptions, setAccountManagerOptions] = useState<
    SelectOption[]
  >([]);
  const [isLoading, setIsLoading] = useState(true);
  const [refreshKey, setRefreshKey] = useState(0);

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

    const load = async () => {
      setIsLoading(true);
      try {
        const allUsers = await getAllUsers();
        const usersList: User[] = Array.isArray(allUsers) ? allUsers : [];

        // Build name + designation maps and the active-user list from one fetch
        const nameMap = new Map<string, string>();
        const designationMap = new Map<string, string | null>();
        usersList.forEach((u) => {
          if (u?.userId) {
            nameMap.set(u.userId, u.userName);
            designationMap.set(u.userId, u.userDesignation);
          }
        });
        const activeUserList = usersList.filter(
          (u) => u.active && !u.userDeleted,
        );

        const [memberships, rawFxResponse] = await Promise.all([
          getManagerMemberships(),
          getAllFXRate(),
        ]);

        // Build FxRateMap (year -> currency -> rate) from the raw response
        const builtFxRateMap: FxRateMap = new Map();
        rawFxResponse.content?.forEach((item) => {
          Object.entries(item.fxRateDetails || {}).forEach(
            ([year, currencyData]) => {
              if (!currencyData) return;
              Object.entries(currencyData).forEach(([, rateData]) => {
                const currency = rateData?.currency?.toUpperCase();
                const rateValue = rateData?.fxRate;
                if (
                  !year ||
                  !currency ||
                  rateValue === null ||
                  rateValue === undefined ||
                  isNaN(rateValue)
                ) {
                  return;
                }
                if (!builtFxRateMap.has(year)) {
                  builtFxRateMap.set(year, new Map());
                }
                builtFxRateMap.get(year)!.set(currency, rateValue);
              });
            },
          );
        });

        // Build manager option lists, deduped by userId
        const toOptions = (members: RoleMembership[]): SelectOption[] => {
          const options: SelectOption[] = [];
          members.forEach((member) => {
            const name = nameMap.get(member.userId);
            if (name) options.push({ value: member.userId, label: name });
          });
          return Array.from(
            new Map(options.map((opt) => [opt.value, opt])).values(),
          );
        };

        if (!cancelled) {
          setUserNameMap(nameMap);
          setUserDesignationMap(designationMap);
          setActiveUsers(activeUserList);
          setFxRateMap(builtFxRateMap);
          setFxRateResponse(rawFxResponse);
          setProjectManagerOptions(toOptions(memberships.projectManagerMembers));
          setAccountManagerOptions(toOptions(memberships.accountManagerMembers));
        }
      } catch (err) {
        console.error("AppCacheProvider: Failed to load maps", err);
      } finally {
        if (!cancelled) setIsLoading(false);
      }
    };

    load();

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

  const refresh = () => setRefreshKey((k) => k + 1);

  return (
    <AppCacheContext.Provider
      value={{
        userNameMap,
        userDesignationMap,
        activeUsers,
        fxRateMap,
        fxRateResponse,
        projectManagerOptions,
        accountManagerOptions,
        isLoading,
        refresh,
      }}
    >
      {children}
    </AppCacheContext.Provider>
  );
}

export function useAppCache(): AppCacheState {
  return useContext(AppCacheContext);
}
