/* ============================================================
   محرك البث المباشر — منصة خبرة
   يراقب مصدر البيانات ويبلّغ الصفحة عند أي تغيير، مع رصد
   الفروقات في النسب حتى تُعرض حركة الصعود والنزول.
   ============================================================ */

window.EXPLive = (function(){

  const STORE_KEY = "exp_ambassadors_data";

  /* ---------- قراءة المصدر ---------- */
  function readDraft(){
    try{
      const s = localStorage.getItem(STORE_KEY);
      if(s) return JSON.parse(s);
    }catch(e){}
    return null;
  }

  /* إعادة تحميل data.js متجاوزًا ذاكرة المتصفح (احتياطي) */
  function readFile(){
    return new Promise((resolve, reject)=>{
      const s = document.createElement("script");
      s.src = "data.js?v=" + Date.now();
      s.onload  = () => { s.remove(); resolve(window.EXP_DATA || null); };
      s.onerror = () => { s.remove(); reject(new Error("data.js")); };
      document.head.appendChild(s);
    });
  }

  /* ============================================================
     ترتيب المصادر:
     ① قاعدة البيانات عبر api/data.php  ← المصدر الرسمي
     ② ملف data.js                      ← إذا تعذّر الاتصال
     ③ مسوّدة المتصفح                    ← فقط في وضع عدم الاتصال
     ============================================================ */
  function read(){
    if(window.EXP && typeof EXP.fetchRemote === "function"){
      return EXP.fetchRemote().then(d => d || readDraft() || readFile().catch(()=>null));
    }
    const d = readDraft();
    if(d) return Promise.resolve(d);
    return readFile().catch(()=> null);
  }

  /* ---------- رصد الفروقات ---------- */
  const keyOf = w => (w.cat||"") + "|" + (w.name||"");

  function scoreMap(data){
    const m = new Map();
    ((data && data.winners) || []).forEach(w => m.set(keyOf(w), Number(w.score)||0));
    return m;
  }

  function diff(oldData, newData){
    const a = scoreMap(oldData), b = scoreMap(newData);
    const out = new Map();
    b.forEach((v,k)=>{
      if(!a.has(k)) return;                    // مرشح جديد — لا يُحتسب فرقًا
      const d = v - a.get(k);
      if(Math.abs(d) > 0.0001) out.set(k, d);
    });
    return out;
  }

  /* ---------- الحلقة ---------- */
  function start(opts){
    const o = Object.assign({
      intervalMs: 20000,
      onUpdate: () => {},     // (data, deltas, meta)
      onTick:   () => {}      // يُستدعى بعد كل محاولة
    }, opts || {});

    let current = o.initial || null;
    let last = JSON.stringify(current);
    let stamp = new Date();
    let timer = null, busy = false;

    function check(force){
      if(busy) return Promise.resolve(false);
      busy = true;
      return read().then(data=>{
        busy = false;
        if(!data) return false;
        const str = JSON.stringify(data);
        if(str === last && !force){ o.onTick(stamp, false); return false; }
        const deltas = diff(current, data);
        current = data; last = str; stamp = new Date();
        o.onUpdate(data, deltas, {stamp});
        o.onTick(stamp, true);
        return true;
      }).catch(()=>{ busy = false; return false; });
    }

    timer = setInterval(check, Math.max(3000, o.intervalMs));

    /* تحديث فوري عند التعديل من لوحة التحكم في تبويب آخر */
    addEventListener("storage", e => { if(e.key === STORE_KEY) check(); });

    /* تحديث عند العودة إلى التبويب */
    addEventListener("visibilitychange", () => { if(!document.hidden) check(); });

    return {
      check,
      stop(){ clearInterval(timer); },
      stamp(){ return stamp; }
    };
  }

  /* ---------- عدّاد رقمي متحرك ----------
     القيمة النهائية مضمونة دائمًا: إذا تعطّلت الحركة (تبويب في الخلفية،
     شاشة عرض غير نشطة، أو تفضيل تقليل الحركة) يُكتب الرقم الصحيح مباشرة.
  --------------------------------- */
  const now = () => (typeof performance === "object" && performance.now)
    ? performance.now() : Date.now();

  function countUp(el, from, to, ms, fmt){
    if(!el) return;
    const f = fmt || (v => Math.round(v*100) + "%");
    const finish = () => { el.textContent = f(to); };

    const reduced = typeof matchMedia === "function" &&
                    matchMedia("(prefers-reduced-motion: reduce)").matches;
    if(!(ms > 0) || from === to || reduced ||
       typeof requestAnimationFrame !== "function"){ finish(); return; }

    const t0 = now();
    let done = false;
    el.textContent = f(from);

    function step(t){
      if(done) return;
      let p = ((typeof t === "number" ? t : now()) - t0) / ms;
      if(!isFinite(p) || p < 0) p = 0;
      if(p > 1) p = 1;
      const e = 1 - Math.pow(1 - p, 3);          // تباطؤ في النهاية
      el.textContent = f(from + (to - from) * e);
      if(p < 1) requestAnimationFrame(step);
      else { done = true; finish(); }
    }
    requestAnimationFrame(step);

    /* ضمانة نهائية لو لم تُستدعَ الحركة أصلًا */
    setTimeout(()=>{ if(!done){ done = true; finish(); } }, ms + 400);
  }

  /* ---------- إعادة ترتيب متحركة (FLIP) ---------- */
  function flip(container, selector, mutate){
    const before = new Map();
    container.querySelectorAll(selector).forEach(el=>{
      if(el.dataset.key) before.set(el.dataset.key, el.getBoundingClientRect());
    });

    mutate();

    container.querySelectorAll(selector).forEach(el=>{
      const b = before.get(el.dataset.key);
      if(!b) return;
      const a = el.getBoundingClientRect();
      const dx = b.left - a.left, dy = b.top - a.top;
      if(!dx && !dy) return;
      el.style.transition = "none";
      el.style.transform  = `translate(${dx}px, ${dy}px)`;
      requestAnimationFrame(()=>{
        el.style.transition = "transform .75s cubic-bezier(.22,1,.36,1)";
        el.style.transform  = "";
        setTimeout(()=>{ el.style.transition = ""; }, 800);
      });
    });
  }

  /* ---------- نص "آخر تحديث" ---------- */
  function ago(d){
    const s = Math.max(0, Math.floor((Date.now() - d.getTime())/1000));
    if(s < 10)   return "الآن";
    if(s < 60)   return `قبل ${s} ثانية`;
    const m = Math.floor(s/60);
    if(m < 60)   return `قبل ${m} دقيقة`;
    const h = Math.floor(m/60);
    return `قبل ${h} ساعة`;
  }

  return {start, countUp, flip, ago, read, STORE_KEY};
})();
