"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { useProfile } from "@/lib/profile/context";
import { addPlaySeconds, startPlaySession, addAnalyticsEvent } from "@/lib/profile/db";
import { evaluateAchievements } from "@/lib/profile/achievements";
import { getCompetitiveAdapter } from "@/lib/adapters/competitive";
import { AchievementToast } from "@/components/PlayStats";

/**
 * Tracks focused play time for a catalog game and flushes to IndexedDB.
 */
export function usePlaySession(gameSlug: string, active: boolean) {
  const { profile, account } = useProfile();
  const [toastIds, setToastIds] = useState<string[]>([]);
  const started = useRef(false);
  const accum = useRef(0);
  const tickAt = useRef<number | null>(null);
  const profileId = profile?.id;

  const flush = useCallback(
    async (final = false) => {
      if (!profileId || !active) return;
      if (tickAt.current != null) {
        accum.current += (Date.now() - tickAt.current) / 1000;
        tickAt.current = Date.now();
      }
      const secs = Math.floor(accum.current);
      if (secs < 1) return;
      accum.current -= secs;
      await addPlaySeconds(profileId, gameSlug, secs);
      const competitive = getCompetitiveAdapter();
      if (await competitive.isEnrolled()) {
        await competitive.submitPlayTime(gameSlug, secs);
      }
      const fresh = await evaluateAchievements(profileId);
      if (fresh.length) {
        setToastIds(fresh.map((f) => f.achievementId));
        for (const u of fresh) {
          await competitive.unlockAchievement(u.achievementId);
        }
      }
      if (final && account) {
        await addAnalyticsEvent({
          type: "session_end",
          accountId: account.id,
          profileId,
          gameSlug,
          value: secs,
          at: Date.now(),
        });
      }
    },
    [profileId, gameSlug, active, account],
  );

  useEffect(() => {
    if (!active || !profileId) return;
    let cancelled = false;
    (async () => {
      if (!started.current) {
        started.current = true;
        await startPlaySession(profileId, gameSlug);
        await addAnalyticsEvent({
          type: "session_start",
          accountId: account?.id,
          profileId,
          gameSlug,
          at: Date.now(),
        });
        const fresh = await evaluateAchievements(profileId);
        if (!cancelled && fresh.length) {
          setToastIds(fresh.map((f) => f.achievementId));
          const competitive = getCompetitiveAdapter();
          for (const u of fresh) {
            await competitive.unlockAchievement(u.achievementId);
          }
        }
      }
      tickAt.current = Date.now();
    })();

    const interval = window.setInterval(() => {
      void flush(false);
    }, 15_000);

    const onVis = () => {
      if (document.hidden) {
        void flush(false);
        tickAt.current = null;
      } else {
        tickAt.current = Date.now();
      }
    };
    document.addEventListener("visibilitychange", onVis);

    return () => {
      cancelled = true;
      window.clearInterval(interval);
      document.removeEventListener("visibilitychange", onVis);
      void flush(true);
    };
  }, [active, profileId, gameSlug, account?.id, flush]);

  const toast = (
    <AchievementToast ids={toastIds} onDone={() => setToastIds([])} />
  );

  return { toast };
}
