import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import {
  createHousehold as createHouseholdApi,
  getUserHouseholds,
  reorderHouseholds as reorderHouseholdsApi,
} from '../api/households';
import { isTransientApiError } from '../api/offlineCache';
import { AuthContext } from './AuthContext';

const ACTIVE_HOUSEHOLD_STORAGE_KEY = 'activeHouseholdId';

export const HouseholdContext = createContext({
  households: [],
  activeHousehold: null,
  loading: false,
  hasLoaded: false,
  error: null,
  setActiveHousehold: () => { },
  refreshHouseholds: () => { },
  createHousehold: () => { },
  reorderHouseholds: () => { },
});

export const HouseholdProvider = ({ children }) => {
  const { token } = useContext(AuthContext);
  const [households, setHouseholds] = useState([]);
  const [activeHousehold, setActiveHouseholdState] = useState(null);
  const [loading, setLoading] = useState(false);
  const [hasLoaded, setHasLoaded] = useState(false);
  const [error, setError] = useState(null);

  const clearActiveHousehold = useCallback(() => {
    setActiveHouseholdState(null);
    localStorage.removeItem(ACTIVE_HOUSEHOLD_STORAGE_KEY);
  }, []);

  const loadHouseholds = useCallback(async () => {
    if (!token) return;

    setLoading(true);
    setError(null);
    try {
      const response = await getUserHouseholds();
      const nextHouseholds = Array.isArray(response.data) ? response.data : [];
      setHouseholds(nextHouseholds);

      if (nextHouseholds.length === 0) {
        clearActiveHousehold();
      }
    } catch (err) {
      console.error('[HouseholdContext] Failed to load households:', err);
      setError(
        err.response?.data?.error?.message ||
        err.response?.data?.message ||
        'Failed to load households'
      );
      if (!isTransientApiError(err)) {
        setHouseholds([]);
        clearActiveHousehold();
      }
    } finally {
      setLoading(false);
      setHasLoaded(true);
    }
  }, [clearActiveHousehold, token]);

  // Load households on mount and when token changes
  useEffect(() => {
    if (token) {
      setHasLoaded(false);
      loadHouseholds();
    } else {
      setHouseholds([]);
      clearActiveHousehold();
      setError(null);
      setLoading(false);
      setHasLoaded(false);
    }
  }, [clearActiveHousehold, loadHouseholds, token]);

  // Load active household from localStorage on mount
  useEffect(() => {
    if (households.length === 0) {
      setActiveHouseholdState(null);
      return;
    }

    const savedHouseholdId = localStorage.getItem(ACTIVE_HOUSEHOLD_STORAGE_KEY);
    if (savedHouseholdId) {
      const household = households.find((candidate) => String(candidate.id) === savedHouseholdId);
      if (household) {
        setActiveHouseholdState(household);
        return;
      }
    }

    // No saved household or not found, use first one
    setActiveHouseholdState(households[0]);
    localStorage.setItem(ACTIVE_HOUSEHOLD_STORAGE_KEY, String(households[0].id));
  }, [households]);

  const setActiveHousehold = (household) => {
    setActiveHouseholdState(household);
    if (household) {
      localStorage.setItem(ACTIVE_HOUSEHOLD_STORAGE_KEY, String(household.id));
    } else {
      localStorage.removeItem(ACTIVE_HOUSEHOLD_STORAGE_KEY);
    }
  };

  const createHousehold = async (name) => {
    try {
      const response = await createHouseholdApi(name);
      const newHousehold = response.data.household;

      // Refresh households list
      await loadHouseholds();

      // Set new household as active
      setActiveHousehold(newHousehold);

      return newHousehold;
    } catch (err) {
      console.error('Failed to create household:', err);
      throw err;
    }
  };

  const reorderHouseholds = async (orderedHouseholdIds) => {
    const householdById = new Map(
      households.map((household) => [String(household.id), household])
    );
    const nextHouseholds = orderedHouseholdIds
      .map((householdId) => householdById.get(String(householdId)))
      .filter(Boolean);

    if (nextHouseholds.length !== households.length) {
      throw new Error("Household order is out of date");
    }

    const previousHouseholds = households;
    setHouseholds(nextHouseholds);
    if (activeHousehold) {
      const nextActiveHousehold = nextHouseholds.find(
        (household) => String(household.id) === String(activeHousehold.id)
      );
      if (nextActiveHousehold) {
        setActiveHouseholdState(nextActiveHousehold);
      }
    }

    try {
      const response = await reorderHouseholdsApi(orderedHouseholdIds);
      const savedHouseholds = Array.isArray(response.data.households)
        ? response.data.households
        : [];

      if (savedHouseholds.length > 0) {
        setHouseholds(savedHouseholds);
        if (activeHousehold) {
          const savedActiveHousehold = savedHouseholds.find(
            (household) => String(household.id) === String(activeHousehold.id)
          );
          if (savedActiveHousehold) {
            setActiveHouseholdState(savedActiveHousehold);
          }
        }
      }

      return savedHouseholds;
    } catch (err) {
      setHouseholds(previousHouseholds);
      if (activeHousehold) {
        setActiveHouseholdState(activeHousehold);
      }
      throw err;
    }
  };

  const value = {
    households,
    activeHousehold,
    loading,
    hasLoaded,
    error,
    setActiveHousehold,
    refreshHouseholds: loadHouseholds,
    createHousehold,
    reorderHouseholds,
  };

  return (
    <HouseholdContext.Provider value={value}>
      {children}
    </HouseholdContext.Provider>
  );
};
