// Global state — fully API-driven

// ── Fetch helper ──────────────────────────────────────────────────────────────
const api = (method, url, body) =>
  fetch(url, {
    method,
    credentials: 'include',
    headers: body ? { 'Content-Type': 'application/json' } : {},
    body: body ? JSON.stringify(body) : undefined,
  }).then(async (res) => {
    const data = await res.json();
    if (!data.ok) throw new Error(data.error || 'Erro desconhecido');
    return data;
  });

// ── Date helpers (shared with parts.jsx via window) ──────────────────────────
const toDateStr = (d) => {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
};

const todayStr = () => toDateStr(new Date());

// Is a recurring quest due today and not yet completed?
const isRecurringDueToday = (q) => {
  if (!q.recurrence) return false;
  const today      = todayStr();
  const done       = new Set(q.weekCompletions || []);
  if (done.has(today)) return false;
  const DAY_KEYS   = ['dom','seg','ter','qua','qui','sex','sab']; // 0=Sun..6=Sat
  const todayKey   = DAY_KEYS[new Date().getDay()];
  if (q.recurrence === 'daily')    return true;
  if (q.recurrence === 'weekdays') return ['seg','ter','qua','qui','sex'].includes(todayKey);
  if (q.recurrence === 'weekend')  return ['sab','dom'].includes(todayKey);
  return q.recurrence.split(',').includes(todayKey);
};

window.toDateStr           = toDateStr;
window.todayStr            = todayStr;
window.isRecurringDueToday = isRecurringDueToday;

// ── Main hook ─────────────────────────────────────────────────────────────────
const useGameState = () => {
  const [user,        setUser]        = React.useState(null);
  const [authLoading, setAuthLoading] = React.useState(true);
  const [quests,      setQuests]      = React.useState([]);
  const [history,     setHistory]     = React.useState([]);
  const [heatData,    setHeatData]    = React.useState(Array(140).fill(0));
  const [ranking,     setRanking]     = React.useState([]);
  const [route,       setRoute]       = React.useState('home');
  const [showForge,   setShowForge]   = React.useState(false);
  const [celeb,       setCeleb]       = React.useState(null);
  const [toasts,      setToasts]      = React.useState([]);

  React.useEffect(() => {
    api('GET', 'api/auth/me.php')
      .then((data) => { setUser(data.user); return loadAll(); })
      .catch(() => {})
      .finally(() => setAuthLoading(false));
  }, []);

  const loadAll = async () => {
    const [qRes, hRes, heatRes, rankRes] = await Promise.all([
      api('GET', 'api/quests/list.php'),
      api('GET', 'api/history/list.php'),
      api('GET', 'api/activity/heatmap.php'),
      api('GET', 'api/ranking/list.php'),
    ]);
    setQuests(qRes.quests);
    setHistory(hRes.history);
    setHeatData(heatRes.heat);
    setRanking(rankRes.ranking);
  };

  // ── Auth ────────────────────────────────────────────────────────────────────
  const login = async (email, password) => {
    const data = await api('POST', 'api/auth/login.php', { email, password });
    setUser(data.user);
    document.documentElement.setAttribute('data-theme', data.user.theme || 'dark');
    await loadAll();
  };

  const register = async (name, email, password) => {
    const data = await api('POST', 'api/auth/register.php', { name, email, password });
    setUser(data.user);
    document.documentElement.setAttribute('data-theme', data.user.theme || 'dark');
    await loadAll();
  };

  const logout = async () => {
    await api('POST', 'api/auth/logout.php');
    setUser(null); setQuests([]); setHistory([]);
    setHeatData(Array(140).fill(0)); setRanking([]); setRoute('home');
  };

  const updateUser = async (updates) => {
    const data = await api('POST', 'api/user/update.php', updates);
    setUser(data.user);
    if (updates.theme) document.documentElement.setAttribute('data-theme', updates.theme);
  };

  // ── Toasts ──────────────────────────────────────────────────────────────────
  const pushToast = (toast) => {
    const id = Date.now() + Math.random();
    setToasts((t) => [...t, { ...toast, id }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 2900);
  };

  // ── Quest: complete one-time ─────────────────────────────────────────────────
  const completeQuest = async (id) => {
    const q = quests.find((x) => x.id === id);
    if (!q || q.status === 'done' || q.recurrence) return;

    const oldLevel = user?.lvl?.level ?? 1;
    setQuests((qs) => qs.map((x) => x.id === id ? { ...x, status: 'done', completedAt: Date.now() } : x));

    try {
      const data = await api('POST', 'api/quests/complete.php', { id });
      setUser((u) => ({ ...u, ...data.stats }));
      pushToast({ kind: 'xp', title: 'Missão concluída!', xp: q.xp });
      if (data.stats.lvl.level > oldLevel) setTimeout(() => setCeleb({ newLevel: data.stats.lvl.level }), 350);

      const [hRes, heatRes, rankRes] = await Promise.all([
        api('GET', 'api/history/list.php'),
        api('GET', 'api/activity/heatmap.php'),
        api('GET', 'api/ranking/list.php'),
      ]);
      setHistory(hRes.history);
      setHeatData(heatRes.heat);
      setRanking(rankRes.ranking);
    } catch (err) {
      setQuests((qs) => qs.map((x) => x.id === id ? { ...x, status: 'open', completedAt: null } : x));
      pushToast({ kind: 'error', title: 'Erro', message: err.message });
    }
  };

  // ── Quest: complete a specific day of a recurring quest ──────────────────────
  const completeDayRecurring = async (questId, date) => {
    const q = quests.find((x) => x.id === questId);
    if (!q || !q.recurrence) return;

    const oldLevel = user?.lvl?.level ?? 1;

    // Optimistic: add date to weekCompletions
    setQuests((qs) => qs.map((x) =>
      x.id === questId
        ? { ...x, weekCompletions: [...(x.weekCompletions || []), date] }
        : x
    ));

    try {
      const data = await api('POST', 'api/quests/complete_day.php', { id: questId, date });
      setUser((u) => ({ ...u, ...data.stats }));
      pushToast({ kind: 'xp', title: 'Dia concluído!', xp: q.xp });
      if (data.stats.lvl.level > oldLevel) setTimeout(() => setCeleb({ newLevel: data.stats.lvl.level }), 350);

      const [hRes, heatRes] = await Promise.all([
        api('GET', 'api/history/list.php'),
        api('GET', 'api/activity/heatmap.php'),
      ]);
      setHistory(hRes.history);
      setHeatData(heatRes.heat);
    } catch (err) {
      // Revert
      setQuests((qs) => qs.map((x) =>
        x.id === questId
          ? { ...x, weekCompletions: (x.weekCompletions || []).filter((d) => d !== date) }
          : x
      ));
      pushToast({ kind: 'error', title: 'Erro', message: err.message });
    }
  };

  // ── Quest: forge & delete ────────────────────────────────────────────────────
  const addQuest = async (questData) => {
    try {
      const data = await api('POST', 'api/quests/create.php', questData);
      setQuests((qs) => [data.quest, ...qs]);
      pushToast({ kind: 'forge', title: 'Missão forjada!', xp: data.quest.xp });
      const hRes = await api('GET', 'api/history/list.php');
      setHistory(hRes.history);
    } catch (err) {
      pushToast({ kind: 'error', title: 'Erro ao forjar', message: err.message });
    }
  };

  const deleteQuest = async (id) => {
    setQuests((qs) => qs.filter((x) => x.id !== id));
    try {
      await api('POST', 'api/quests/delete.php', { id });
    } catch (err) {
      const qRes = await api('GET', 'api/quests/list.php');
      setQuests(qRes.quests);
      pushToast({ kind: 'error', title: 'Erro ao excluir', message: err.message });
    }
  };

  // ── Derived ──────────────────────────────────────────────────────────────────
  const totalXp    = user?.totalXp    ?? 0;
  const lvl        = user?.lvl        ?? { level: 1, intoLevel: 0, needLevel: 500 };
  const tier       = user?.tier       ?? { name: 'Iniciante', idx: 0 };
  const streak     = user?.streak     ?? 0;
  const bestStreak = user?.bestStreak ?? 0;

  const totalCompleted    = quests.filter((q) => q.status === 'done').length;
  const completedByRarity = quests
    .filter((q) => q.status === 'done')
    .reduce((acc, q) => { acc[q.rarity] = (acc[q.rarity] || 0) + 1; return acc; }, {});

  const stateForBadges = { xp: totalXp, streak, totalCompleted, completedByRarity };
  const unlockedBadges = BADGES.filter((b) => b.cond(stateForBadges));
  const dismissCeleb   = () => setCeleb(null);

  return {
    user, authLoading, login, register, logout, updateUser,
    quests, history, heatData, ranking,
    streak, bestStreak, totalXp, lvl, tier,
    totalCompleted, unlockedBadges, stateForBadges,
    route, setRoute, showForge, setShowForge,
    celeb, dismissCeleb, toasts,
    completeQuest, completeDayRecurring, addQuest, deleteQuest,
  };
};

window.useGameState = useGameState;
window.api          = api;
