/* eslint-disable react-refresh/only-export-components */
/**
 * AppContext - Global application state.
 *
 * Manages:
 *  - Language preference (English / Hindi / Gujarati) with persistence
 *  - User preferences (notifications, etc.)
 *  - Global loading state
 *  - Global error state
 */

import { createContext, useReducer, useEffect, useCallback } from "react";
import { useTranslation } from "react-i18next";
import storage from "@utils/storage";
import {
  STORAGE_KEYS,
  LANGUAGES,
  DEFAULT_LANGUAGE,
} from "@utils/constants";

// ---------------------------------------------------------------------------
// Initial State
// ---------------------------------------------------------------------------

function loadPersistedPreferences() {
  return storage.get(STORAGE_KEYS.USER_PREFERENCES, {
    notifications: true,
  });
}

function buildInitialState() {
  return {
    language: storage.get(STORAGE_KEYS.LANGUAGE, DEFAULT_LANGUAGE),
    preferences: loadPersistedPreferences(),
    loading: false,
    loadingMessage: "",
    error: null,
  };
}

// ---------------------------------------------------------------------------
// Action Types
// ---------------------------------------------------------------------------

const ACTION_TYPES = {
  SET_LANGUAGE: "SET_LANGUAGE",
  SET_PREFERENCES: "SET_PREFERENCES",
  SET_LOADING: "SET_LOADING",
  SET_ERROR: "SET_ERROR",
  CLEAR_ERROR: "CLEAR_ERROR",
  RESET: "RESET",
};

// ---------------------------------------------------------------------------
// Reducer
// ---------------------------------------------------------------------------

function appReducer(state, action) {
  switch (action.type) {
    case ACTION_TYPES.SET_LANGUAGE:
      return { ...state, language: action.payload };

    case ACTION_TYPES.SET_PREFERENCES:
      return {
        ...state,
        preferences: { ...state.preferences, ...action.payload },
      };

    case ACTION_TYPES.SET_LOADING:
      return {
        ...state,
        loading: action.payload.loading,
        loadingMessage: action.payload.message || "",
      };

    case ACTION_TYPES.SET_ERROR:
      return { ...state, error: action.payload, loading: false };

    case ACTION_TYPES.CLEAR_ERROR:
      return { ...state, error: null };

    case ACTION_TYPES.RESET:
      return buildInitialState();

    default:
      return state;
  }
}

// ---------------------------------------------------------------------------
// Context
// ---------------------------------------------------------------------------

export const AppContext = createContext(null);

// ---------------------------------------------------------------------------
// Provider
// ---------------------------------------------------------------------------

export function AppProvider({ children }) {
  const [state, dispatch] = useReducer(appReducer, null, buildInitialState);
  const { i18n } = useTranslation();

  // Persist language and sync with i18n whenever it changes
  useEffect(() => {
    storage.set(STORAGE_KEYS.LANGUAGE, state.language);
    document.documentElement.lang = state.language;
    if (i18n.language !== state.language) {
      i18n.changeLanguage(state.language);
    }
  }, [state.language, i18n]);

  // Persist preferences whenever they change
  useEffect(() => {
    storage.set(STORAGE_KEYS.USER_PREFERENCES, state.preferences);
  }, [state.preferences]);

  // --- Actions ---------------------------------------------------------------

  const setLanguage = useCallback((lang) => {
    const validLangs = Object.values(LANGUAGES);
    if (!validLangs.includes(lang)) {
      console.error(
        `[AppContext] Invalid language "${lang}". Expected one of: ${validLangs.join(", ")}`,
      );
      return;
    }
    dispatch({ type: ACTION_TYPES.SET_LANGUAGE, payload: lang });
  }, []);

  const actions = {
    setLanguage,

    toggleLanguage: () => {
      const langs = [LANGUAGES.EN, LANGUAGES.HI, LANGUAGES.GU];
      const currentIndex = langs.indexOf(state.language);
      const nextIndex = (currentIndex + 1) % langs.length;
      dispatch({ type: ACTION_TYPES.SET_LANGUAGE, payload: langs[nextIndex] });
    },

    setPreferences: (prefs) => {
      dispatch({ type: ACTION_TYPES.SET_PREFERENCES, payload: prefs });
    },

    setLoading: (loading, message = "") => {
      dispatch({
        type: ACTION_TYPES.SET_LOADING,
        payload: { loading, message },
      });
    },

    setError: (error) => {
      dispatch({ type: ACTION_TYPES.SET_ERROR, payload: error });
    },

    clearError: () => {
      dispatch({ type: ACTION_TYPES.CLEAR_ERROR });
    },

    resetState: () => {
      storage.remove(STORAGE_KEYS.LANGUAGE);
      storage.remove(STORAGE_KEYS.USER_PREFERENCES);
      dispatch({ type: ACTION_TYPES.RESET });
    },
  };

  const value = { ...state, ...actions };

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