const fs = require('fs');
const path = require('path');

/**
 * Statistiques persistantes, cumulees sur TOUS les lives (le fichier survit aux
 * redemarrages). Alimente le tableau de bord prive de la page /simulator.
 *
 * Tout evenement passe ici : les vrais dons TikTok comme ceux envoyes depuis la
 * page de simulation (qui sert aussi de rattrapage quand un don ne part pas).
 */

const DOSSIER = path.join(__dirname, '..', 'data');
const FICHIER = path.join(DOSSIER, 'stats.json');
const DELAI_SAUVEGARDE_MS = 2000;

function statsVides() {
  return {
    version: 1,
    creeLe: new Date().toISOString(),
    lives: [],
    global: {
      diamants: 0,
      dons: 0,
      likes: 0,
      follows: 0,
      commentaires: 0,
      partages: 0
    },
    parDon: {},
    parPersonne: {}
  };
}

function chargerStats() {
  try {
    const brut = JSON.parse(fs.readFileSync(FICHIER, 'utf-8'));
    const base = statsVides();
    return {
      ...base,
      ...brut,
      global: { ...base.global, ...(brut.global || {}) },
      parDon: brut.parDon || {},
      parPersonne: brut.parPersonne || {},
      lives: Array.isArray(brut.lives) ? brut.lives : []
    };
  } catch (e) {
    return statsVides();
  }
}

function personneVide(maintenant) {
  return {
    diamants: 0,
    dons: 0,
    likes: 0,
    follows: 0,
    commentaires: 0,
    partages: 0,
    parDon: {},
    plusGrosDon: null,
    plusGrosDonDiamants: 0,
    avatar: null,
    premierVu: maintenant,
    dernierVu: maintenant,
    livesVus: 0
  };
}

function creerStats() {
  const donnees = chargerStats();
  let sauvegardeEnAttente = null;
  let liveCourant = null;
  const vusCeLive = new Set();

  function planifierSauvegarde() {
    if (sauvegardeEnAttente) return;
    sauvegardeEnAttente = setTimeout(() => {
      sauvegardeEnAttente = null;
      sauvegarderMaintenant();
    }, DELAI_SAUVEGARDE_MS);
  }

  function sauvegarderMaintenant() {
    try {
      fs.mkdirSync(DOSSIER, { recursive: true });
      fs.writeFileSync(FICHIER, JSON.stringify(donnees, null, 2), 'utf-8');
    } catch (e) {
      // on ne casse jamais le live pour un probleme d'ecriture de stats
    }
  }

  function demarrerLive(infos) {
    liveCourant = {
      debut: new Date().toISOString(),
      jeu: infos && infos.jeu,
      pseudoTikTok: (infos && infos.pseudoTikTok) || null,
      diamants: 0,
      dons: 0,
      likes: 0,
      follows: 0,
      personnes: 0
    };
    donnees.lives.push(liveCourant);
    vusCeLive.clear();
    planifierSauvegarde();
  }

  function personne(uniqueId, maintenant) {
    if (!donnees.parPersonne[uniqueId]) {
      donnees.parPersonne[uniqueId] = personneVide(maintenant);
    }
    const p = donnees.parPersonne[uniqueId];
    p.dernierVu = maintenant;
    if (!vusCeLive.has(uniqueId)) {
      vusCeLive.add(uniqueId);
      p.livesVus = (p.livesVus || 0) + 1;
      if (liveCourant) liveCourant.personnes = vusCeLive.size;
    }
    return p;
  }

  function enregistrer(event) {
    if (!event || !event.type) return;
    const uniqueId = event.uniqueId;
    if (!uniqueId) return;

    const maintenant = new Date().toISOString();
    const p = personne(uniqueId, maintenant);
    if (event.profilePictureUrl) p.avatar = event.profilePictureUrl;

    if (event.type === 'gift') {
      const repeat = Number(event.repeatCount) > 0 ? Number(event.repeatCount) : 1;
      const diamants = (Number(event.diamondCount) || 0) * repeat;
      const nom = event.giftName || (event.giftId ? `#${event.giftId}` : 'inconnu');

      donnees.global.dons += repeat;
      donnees.global.diamants += diamants;
      p.dons += repeat;
      p.diamants += diamants;

      if (!donnees.parDon[nom]) donnees.parDon[nom] = { fois: 0, diamants: 0 };
      donnees.parDon[nom].fois += repeat;
      donnees.parDon[nom].diamants += diamants;

      p.parDon[nom] = (p.parDon[nom] || 0) + repeat;
      if (diamants > (p.plusGrosDonDiamants || 0)) {
        p.plusGrosDonDiamants = diamants;
        p.plusGrosDon = nom;
      }

      if (liveCourant) { liveCourant.dons += repeat; liveCourant.diamants += diamants; }
    } else if (event.type === 'like') {
      const taps = Number(event.likeCount) > 0 ? Number(event.likeCount) : 1;
      donnees.global.likes += taps;
      p.likes += taps;
      if (liveCourant) liveCourant.likes += taps;
    } else if (event.type === 'follow') {
      donnees.global.follows += 1;
      p.follows += 1;
      if (liveCourant) liveCourant.follows += 1;
    } else if (event.type === 'comment') {
      donnees.global.commentaires += 1;
      p.commentaires += 1;
    } else if (event.type === 'share') {
      donnees.global.partages += 1;
      p.partages = (p.partages || 0) + 1;
    } else {
      return;
    }

    if (liveCourant) liveCourant.fin = maintenant;
    planifierSauvegarde();
  }

  function resume() {
    const personnes = Object.entries(donnees.parPersonne).map(([pseudo, p]) => ({ pseudo, ...p }));
    const dons = Object.entries(donnees.parDon)
      .map(([nom, d]) => ({ nom, ...d }))
      .sort((a, b) => b.diamants - a.diamants);

    const trier = (cle) => [...personnes].sort((a, b) => (b[cle] || 0) - (a[cle] || 0));

    return {
      creeLe: donnees.creeLe,
      global: {
        ...donnees.global,
        personnes: personnes.length,
        lives: donnees.lives.length,
        // moyennes utiles pour situer un live par rapport aux autres
        diamantsParLive: donnees.lives.length ? Math.round(donnees.global.diamants / donnees.lives.length) : 0,
        likesParLive: donnees.lives.length ? Math.round(donnees.global.likes / donnees.lives.length) : 0,
        diamantsParDonateur: personnes.filter((p) => p.diamants > 0).length
          ? Math.round(donnees.global.diamants / personnes.filter((p) => p.diamants > 0).length)
          : 0,
        donateurs: personnes.filter((p) => p.diamants > 0).length
      },
      parDon: dons,
      topDonateurs: trier('diamants').filter((p) => p.diamants > 0).slice(0, 25),
      topLikers: trier('likes').filter((p) => p.likes > 0).slice(0, 25),
      topCommentateurs: trier('commentaires').filter((p) => p.commentaires > 0).slice(0, 25),
      plusFideles: [...personnes].sort((a, b) => (b.livesVus || 0) - (a.livesVus || 0)).slice(0, 25),
      lives: [...donnees.lives].reverse().slice(0, 30),
      personnes: personnes.length
    };
  }

  function reinitialiser() {
    const neuf = statsVides();
    Object.keys(donnees).forEach((k) => delete donnees[k]);
    Object.assign(donnees, neuf);
    vusCeLive.clear();
    liveCourant = null;
    sauvegarderMaintenant();
  }

  process.on('exit', sauvegarderMaintenant);

  return { enregistrer, resume, reinitialiser, demarrerLive, sauvegarderMaintenant, fichier: FICHIER };
}

module.exports = { creerStats };
