// screens/matchday-achievements.jsx — check and award after a matchday
//
// Runs after a score is saved. Pulls every score this identity has, evaluates
// each badge, awards anything newly earned and pushes it onto the same banner
// queue Draft and Name the XI already use — so a Matchday unlock looks
// identical to any other, which is the point.
//
// Awarding is idempotent server-side (unique index on identity+badge+tier), so
// a re-run can't double-pay. That means this can be called freely without
// tracking what's already been checked.

(function () {

  // Queue for AchievementBannerHost. It reads window._pendingAchievements and
  // listens for 'achievements:queued'.
  function queueBanner(item) {
    window._pendingAchievements = window._pendingAchievements || [];
    window._pendingAchievements.push(item);
    window.dispatchEvent(new Event('achievements:queued'));
  }

  const TIER_ORDER = ['bronze', 'silver', 'gold', 'diamond'];

  // Normalise a score row so the badge checks can read it uniformly.
  function shape(row) {
    return {
      ...row,
      play_date: row.matchday?.play_date || (row.completed_at || '').slice(0, 10),
      solved_types: row.solved_types || [],
      featured_club_ids: row.featured_club_ids || [],
      hints_used: row.hints_used || 0,
    };
  }

  async function checkMatchdayAchievements(anonId, clubId) {
    try {
      const [rowsRaw, held, dates] = await Promise.all([
        window.fetchAllMyMatchdayScores(anonId),
        window.fetchMyMatchdayAchievements(anonId),
        window.fetchAvailableDates(),
      ]);
      const scores = (rowsRaw || []).map(shape);
      if (!scores.length) return [];

      const have = new Set((held || []).map(h => `${h.badge_id}:${h.tier}`));
      const ctx = { availableDates: dates || [], myClubId: clubId || null };
      const rewards = window.MD_TIER_REWARD || {};
      const earned = [];

      // ── general badges ──
      for (const badge of (window.MATCHDAY_BADGES || [])) {
        for (const tier of TIER_ORDER) {
          const key = `${badge.id}:${tier}`;
          if (have.has(key)) continue;
          const t = badge.tiers[tier];
          if (!t) continue;
          let passed = false;
          try { passed = badge.check(scores, t.n, ctx); } catch { passed = false; }
          if (!passed) break;          // tiers are cumulative — stop at the first miss
          earned.push({
            badgeId: badge.id, tier, tokens: rewards[tier] || 0,
            icon: badge.icon, name: badge.name, label: t.label,
          });
        }
      }

      // ── club badges ──
      // Only clubs this player has actually seen, rather than all 62 — checking
      // clubs they've never encountered is pure waste.
      const seen = new Set();
      scores.forEach(s => (s.featured_club_ids || []).forEach(c => seen.add(c)));
      const clubMeta = await window.fetchClubs();
      const byId = {};
      (clubMeta || []).forEach(c => { byId[c.id] = c; });

      for (const cid of seen) {
        const club = byId[cid];
        if (!club || club.tier === 'T3') continue;   // T3 has no mastery to earn
        for (const tier of TIER_ORDER) {
          const key = `club_${club.slug}:${tier}`;
          if (have.has(key)) continue;
          let passed = false;
          try { passed = window.mdClubCheck(scores, cid, tier); } catch { passed = false; }
          if (!passed) break;
          earned.push({
            badgeId: `club_${club.slug}`, tier, tokens: rewards[tier] || 0,
            icon: '🛡️', name: club.name, label: window.MD_CLUB_THRESHOLDS[tier].label,
          });
        }
      }

      // ── award + banner ──
      for (const e of earned) {
        try {
          const res = await window.awardAchievement({
            badgeId: e.badgeId, tier: e.tier, tokens: e.tokens, anonId,
          });
          if (res?.awarded) {
            queueBanner({
              icon: e.icon, title: e.name, subtitle: e.label,
              tier: e.tier, tokens: e.tokens,
            });
          }
        } catch (err) {
          console.warn('award failed', e.badgeId, err.message);
        }
      }

      return earned;
    } catch (e) {
      // Never let achievement checking break the results screen — the score is
      // already saved, and a missed badge is recoverable next time.
      console.warn('achievement check failed:', e.message);
      return [];
    }
  }

  window.checkMatchdayAchievements = checkMatchdayAchievements;
})();
