(() => {
  'use strict';

  const API_ENDPOINTS = ['./telegram-roll.php', '/api/telegram-roll'];
  const STORAGE = {
    bonus: 'diceReferralBonusRollsV2',
    ownerCode: 'diceReferralOwnerCodeV2',
    reported: 'diceReferralReportedV2',
  };

  const $ = (id) => document.getElementById(id);
  const cleanPhone = (value) => {
    let digits = String(value || '').replace(/\D/g, '');
    if (digits.startsWith('60')) digits = `0${digits.slice(2)}`;
    return digits;
  };
  const validCode = (value) => /^[A-Z0-9]{6,16}$/.test(String(value || ''));
  const getRefCode = () => {
    const url = new URL(window.location.href);
    return String(url.searchParams.get('ref') || url.searchParams.get('invite') || '')
      .trim().toUpperCase();
  };
  const simpleHash = (text) => {
    let hash = 2166136261;
    for (const char of String(text)) {
      hash ^= char.charCodeAt(0);
      hash = Math.imul(hash, 16777619);
    }
    return (hash >>> 0).toString(36).toUpperCase();
  };
  const makeInviteCode = (phone) => `PLAY${simpleHash(cleanPhone(phone)).slice(0, 8)}`.slice(0, 12);
  const getPlayer = () => ({
    name: $('playerName')?.value?.trim() || window.playerLoginData?.name || $('loginPlayerName')?.value?.trim() || '',
    memberUsername: $('memberUsername')?.value?.trim() || window.playerLoginData?.memberUsername || $('loginMemberUsername')?.value?.trim() || '',
    phone: $('phoneNumber')?.value?.trim() || window.playerLoginData?.phone || $('loginPhoneNumber')?.value?.trim() || '',
  });
  const getBonus = () => Math.max(0, Number(localStorage.getItem(STORAGE.bonus) || 0));
  const setBonus = (value) => {
    const next = Math.max(0, Math.floor(Number(value) || 0));
    localStorage.setItem(STORAGE.bonus, String(next));
    renderBonus(next);
    window.dispatchEvent(new CustomEvent('dice:bonus-rolls-changed', { detail: { bonusRolls: next } }));
  };

  async function post(payload) {
    let lastError = new Error('Referral server is unavailable.');
    for (const endpoint of API_ENDPOINTS) {
      try {
        const response = await fetch(endpoint, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload),
          cache: 'no-store',
        });
        const data = await response.json().catch(() => ({}));
        if (response.ok && data?.ok) return data;
        lastError = new Error(data?.message || `Request failed (${response.status}).`);
        if (response.status !== 404) break;
      } catch (error) {
        lastError = error;
      }
    }
    throw lastError;
  }

  function updateInviteLinks(code) {
    if (!validCode(code)) return;
    const url = new URL(window.location.href);
    url.searchParams.set('ref', code);
    url.searchParams.delete('invite');
    const inviteUrl = url.toString();
    ['inviteCode', 'resultPopupInviteCode'].forEach((id) => {
      const element = $(id);
      if (element) element.textContent = code;
    });
    document.querySelectorAll('[data-share]').forEach((element) => {
      const channel = element.dataset.share;
      const message = `Play Daily Dice Roll with my invite link: ${inviteUrl}`;
      if (channel === 'WhatsApp') element.href = `https://wa.me/?text=${encodeURIComponent(message)}`;
      if (channel === 'Telegram') element.href = `https://t.me/share/url?url=${encodeURIComponent(inviteUrl)}&text=${encodeURIComponent('Play Daily Dice Roll with me!')}`;
      if (channel === 'LINE') element.href = `https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(inviteUrl)}`;
      if (channel === 'Share' && element.tagName === 'BUTTON') {
        element.dataset.inviteUrl = inviteUrl;
      }
    });
    document.querySelectorAll('#copyInvite, #resultPopupCopyInvite').forEach((button) => {
      button.dataset.inviteUrl = inviteUrl;
    });
  }

  function ensureBadge() {
    let badge = $('referralBonusBadge');
    if (badge) return badge;
    badge = document.createElement('div');
    badge.id = 'referralBonusBadge';
    badge.style.cssText = 'display:none;margin:10px 0 0;padding:10px 14px;border:1px solid rgba(250,204,21,.55);border-radius:12px;background:rgba(250,204,21,.12);color:#ffe66b;font-weight:900;text-align:center';
    const helper = $('rollHelper');
    helper?.insertAdjacentElement('afterend', badge);
    return badge;
  }

  function renderBonus(count = getBonus()) {
    const badge = ensureBadge();
    if (count > 0) {
      badge.style.display = 'block';
      badge.textContent = `INVITE REWARD READY: ${count} EXTRA ROLL${count > 1 ? 'S' : ''}`;
      unlockRollButton();
    } else {
      badge.style.display = 'none';
    }
  }

  function unlockRollButton() {
    if (getBonus() < 1) return;
    const button = $('rollButton');
    if (!button) return;
    button.disabled = false;
    button.dataset.referralBonusReady = 'true';
    const text = $('rollButtonText');
    if (text && /come back|complete|no roll|roll dice/i.test(text.textContent || '')) {
      text.textContent = 'USE EXTRA ROLL';
    }
    const helper = $('rollHelper');
    if (helper) helper.innerHTML = '<span aria-hidden="true">🎁</span> Your friend completed a roll. One extra roll is ready.';
  }

  async function registerAndClaim() {
    const player = getPlayer();
    if (player.name.length < 2 || cleanPhone(player.phone).length < 9) return;
    const code = makeInviteCode(player.phone);
    localStorage.setItem(STORAGE.ownerCode, code);
    updateInviteLinks(code);
    try {
      await post({ event: 'invite_registered', ...player, inviteCode: code });
      const result = await post({ event: 'claim_invite_bonus', ...player, inviteCode: code });
      if (Number(result.bonusRolls) > 0) setBonus(getBonus() + Number(result.bonusRolls));
    } catch (error) {
      console.warn('[Referral bonus]', error.message);
    }
  }

  async function reportSuccessfulReferral() {
    const refCode = getRefCode();
    const player = getPlayer();
    if (!validCode(refCode) || player.name.length < 2 || cleanPhone(player.phone).length < 9) return;
    const key = `${refCode}:${cleanPhone(player.phone)}`;
    let reported = {};
    try { reported = JSON.parse(localStorage.getItem(STORAGE.reported) || '{}'); } catch (_) {}
    if (reported[key]) return;
    try {
      const result = await post({ event: 'referral_used', ...player, inviteCode: refCode });
      reported[key] = Date.now();
      localStorage.setItem(STORAGE.reported, JSON.stringify(reported));
      if (result.inviteBonusAwarded) {
        const note = $('resultPopupReferral');
        const text = $('resultPopupReferralText');
        if (text) text.textContent = 'Invite completed. Your friend received +1 extra roll.';
        if (note) note.hidden = false;
      }
    } catch (error) {
      console.warn('[Referral bonus]', error.message);
    }
  }

  function bindUI() {
    document.addEventListener('click', async (event) => {
      const copyButton = event.target.closest('#copyInvite, #resultPopupCopyInvite');
      if (copyButton?.dataset.inviteUrl) {
        event.preventDefault();
        await navigator.clipboard.writeText(copyButton.dataset.inviteUrl).catch(() => {});
      }
      const shareButton = event.target.closest('[data-share="Share"]');
      if (shareButton?.dataset.inviteUrl && navigator.share) {
        event.preventDefault();
        await navigator.share({ title: document.title, url: shareButton.dataset.inviteUrl }).catch(() => {});
      }
    });

    $('loginForm')?.addEventListener('submit', () => setTimeout(registerAndClaim, 80));
    window.addEventListener('focus', registerAndClaim);
    document.addEventListener('visibilitychange', () => {
      if (!document.hidden) registerAndClaim();
    });

    const rollButton = $('rollButton');
    rollButton?.addEventListener('click', () => {
      if (getBonus() > 0 && rollButton.dataset.referralBonusReady === 'true') {
        rollButton.dataset.consumingReferralBonus = 'true';
      }
    }, true);

    const popup = $('resultPopup');
    if (popup) {
      new MutationObserver(() => {
        if (!popup.hidden) {
          reportSuccessfulReferral();
          const button = $('rollButton');
          if (button?.dataset.consumingReferralBonus === 'true') {
            delete button.dataset.consumingReferralBonus;
            delete button.dataset.referralBonusReady;
            setBonus(getBonus() - 1);
          }
        }
      }).observe(popup, { attributes: true, attributeFilter: ['hidden'] });
    }

    if (rollButton) {
      new MutationObserver(() => unlockRollButton()).observe(rollButton, {
        attributes: true,
        attributeFilter: ['disabled'],
      });
    }
  }

  const ownerCode = localStorage.getItem(STORAGE.ownerCode);
  if (validCode(ownerCode)) updateInviteLinks(ownerCode);
  renderBonus();
  bindUI();
  setTimeout(registerAndClaim, 500);

  window.DiceReferralBonus = {
    getBonusRolls: getBonus,
    claim: registerAndClaim,
    consumeOne() { if (getBonus() > 0) setBonus(getBonus() - 1); },
  };
})();
