import React, { createContext, useContext, useState, useCallback } from "react";
import { useUser, useAuth } from "@clerk/clerk-expo";
import { getUserStatistics } from "../api/statistics";
import type { UserStatisticsResponse } from "../api/types";
import log from "../utils/logger";

interface StatisticsContextValue {
  statistics: UserStatisticsResponse | null;
  loading: boolean;
  error: Error | null;
  refetchStatistics: () => Promise<void>;
  forceRefresh: () => Promise<void>;
  clearCache: () => void;
}

const StatisticsContext = createContext<StatisticsContextValue | undefined>(
  undefined,
);

export function StatisticsProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  const { user } = useUser();
  const { getToken } = useAuth();
  const [statistics, setStatistics] = useState<UserStatisticsResponse | null>(
    null,
  );
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);
  const [lastFetchTime, setLastFetchTime] = useState<number>(0);

  // Cache statistics for 30 seconds to avoid duplicate calls
  const CACHE_DURATION = 30000; // 30 seconds

  const refetchStatistics = useCallback(async () => {
    if (!user?.id) return;

    // Check if we have recent cached data
    const now = Date.now();
    if (statistics && now - lastFetchTime < CACHE_DURATION) {
      log.debug("Using cached statistics", {
        age: now - lastFetchTime,
        cacheRemaining: CACHE_DURATION - (now - lastFetchTime),
      });
      return;
    }

    try {
      setLoading(true);
      setError(null);
      log.debug("Fetching fresh statistics", { userId: user.id });

      const token = await getToken();
      const stats = await getUserStatistics(user.id, token);

      setStatistics(stats);
      setLastFetchTime(now);
      log.debug("Statistics fetched and cached", {
        userId: user.id,
        hasWeeklyTrend: !!stats.weeklyTrend,
        weeklyTrendLength: stats.weeklyTrend?.length || 0,
        weeklyTrendSample: stats.weeklyTrend?.[0],
        stats,
      });
    } catch (err) {
      const error = err instanceof Error ? err : new Error(String(err));
      log.error("Failed to fetch statistics", error);
      setError(error);
    } finally {
      setLoading(false);
    }
  }, [user?.id, getToken, statistics, lastFetchTime]);

  const clearCache = useCallback(() => {
    setStatistics(null);
    setLastFetchTime(0);
    setError(null);
    log.debug("Statistics cache cleared");
  }, []);

  const forceRefresh = useCallback(async () => {
    if (!user?.id) return;

    try {
      setLoading(true);
      setError(null);
      log.debug("Force fetching statistics", { userId: user.id });

      const token = await getToken();
      const stats = await getUserStatistics(user.id, token);

      setStatistics(stats);
      setLastFetchTime(Date.now());
      log.debug("Statistics force fetched and cached", {
        userId: user.id,
        hasWeeklyTrend: !!stats.weeklyTrend,
        weeklyTrendLength: stats.weeklyTrend?.length || 0,
        weeklyTrendSample: stats.weeklyTrend?.[0],
        stats,
      });
    } catch (err) {
      const error = err instanceof Error ? err : new Error(String(err));
      log.error("Failed to force fetch statistics", error);
      setError(error);
    } finally {
      setLoading(false);
    }
  }, [user?.id, getToken]);

  return (
    <StatisticsContext.Provider
      value={{
        statistics,
        loading,
        error,
        refetchStatistics,
        forceRefresh,
        clearCache,
      }}
    >
      {children}
    </StatisticsContext.Provider>
  );
}

export function useStatistics() {
  const context = useContext(StatisticsContext);
  if (context === undefined) {
    throw new Error("useStatistics must be used within a StatisticsProvider");
  }
  return context;
}
