function safeNumber(value) {
  if (value == null || value === '') return null;
  const parsed = Number(value);
  if (Number.isNaN(parsed)) return null;
  return parsed;
}

function parsePercentValue(value) {
  if (value == null) return null;
  if (typeof value === 'number') return value;
  const normalized = String(value).replace('%', '').trim();
  return safeNumber(normalized);
}

function normalizeShareValue(value) {
  const num = parsePercentValue(value);
  if (num == null) return null;
  if (num > 0 && num <= 1) {
    return num * 100;
  }
  return num;
}

export function formatThDisplay(value) {
  const num = safeNumber(value);
  const formatted = num == null ? '0' : (num >= 10 ? num.toFixed(0) : num.toFixed(1));
  return `${formatted} TH/s`;
}

export function formatPercentDisplay(value) {
  const num = normalizeShareValue(value);
  const displayNum = num == null ? 0 : num;
  return `${displayNum.toFixed(1)}%`;
}

export function formatRewardValue(value) {
  const num = safeNumber(value);
  const displayNum = num == null ? 0 : num;
  return `${displayNum.toFixed(2)} GMT`;
}

export function parseSnapshotArray(value) {
  if (!value) return [];
  try {
    const parsed = typeof value === 'string' ? JSON.parse(value) : value;
    if (Array.isArray(parsed)) return parsed;
    return [];
  } catch (err) {
    console.warn('[MW] parseSnapshotArray failed', err);
  }
  return [];
}

export function parseLeadingClans(record = {}) {
  const raw = record.leading_clans_snapshot ?? record.leading_clans ?? '[]';
  const data = parseSnapshotArray(raw);
  return data.map((entry) => ({
    name: entry?.name ?? entry?.clan_name ?? entry?.clanName ?? 'Unknown',
    th: formatThDisplay(entry?.th_per_s ?? entry?.clan_th_per_s ?? entry?.th_per_s_value),
    pct: formatPercentDisplay(entry?.share ?? entry?.percentage ?? entry?.pct ?? entry?.clan_percentage)
  }));
}

export function describeRoundRecord(record = {}) {
  return {
    winner: record.clan_name ?? 'Unknown',
    winnerTh: formatThDisplay(record.clan_th_per_s),
    winnerPct: formatPercentDisplay(record.clan_percentage),
    player: record.winner_player_name ?? 'N/A',
    playerTh: formatThDisplay(record.player_th_per_s),
    playerPct: formatPercentDisplay(record.player_percentage),
    playerReward: safeNumber(record.winner_reward_gmt) != null
      ? `${safeNumber(record.winner_reward_gmt).toFixed(2)} GMT`
      : '0.00 GMT'
  };
}

export function readXpath(path, doc = document) {
  if (!path) return null;
  try {
    const resolver = doc.createNSResolver(doc.documentElement);
    const result = doc.evaluate(path, doc, resolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
    return result.singleNodeValue || null;
  } catch (err) {
    console.warn('[MW] xpath read failed', path, err);
    return null;
  }
}

export function extractCurrentRoundData(doc = document) {
  try {
    const data = {
      blockId: null,
      multiplier: null,
      timer: null,
      leadingClan: null
    };

    // XPath voor block ID (round number)
    const ROUND_ID_XPATHS = [
      '/html/body/app-root/main/miner-wars/div/div/div/miner-wars-main/miner-wars-game/div/div[1]/div/div[1]/a/div[2]/span',
      '/html/body/app-root/main/miner-wars/div/div/div/miner-wars-main/miner-wars-game/div/div[1]/div/div[1]/a/div[2]'
    ];

    // XPath voor multiplier
    const MULTIPLIER_XPATHS = [
      '/html/body/app-root/main/miner-wars/div/div/div/miner-wars-main/miner-wars-game/div/div[1]/div/div[1]/a/div[3]'
    ];

    // XPath voor timer
    const TIMER_XPATHS = [
      '/html/body/app-root/main/miner-wars/div/div/div/miner-wars-main/miner-wars-game/div/div[1]/div/div[2]/div/div',
      '/html/body/app-root/main/miner-wars/div/div/div/miner-wars-main/miner-wars-game/div/div[1]/div/div[2]'
    ];

    // Try to extract using XPaths
    for (const xpath of ROUND_ID_XPATHS) {
      const node = readXpath(xpath, doc);
      if (node && node.textContent) {
        data.blockId = node.textContent.trim();
        break;
      }
    }

    for (const xpath of MULTIPLIER_XPATHS) {
      const node = readXpath(xpath, doc);
      if (node && node.textContent) {
        data.multiplier = node.textContent.trim();
        break;
      }
    }

    for (const xpath of TIMER_XPATHS) {
      const node = readXpath(xpath, doc);
      if (node && node.textContent) {
        data.timer = node.textContent.trim();
        break;
      }
    }

    return data;
  } catch (err) {
    console.warn('[MW] Failed to extract current round data:', err);
    return null;
  }
}

export function extractTop10Players(doc = document) {
  try {
    console.log('[MW] Extracting top 10 players from leaderboard');
    const players = [];

    // Try to find player leaderboard items
    // Adjust selectors based on actual DOM structure
    const playerRows = doc.querySelectorAll('.leaderboard-players .leaderboard-item, .players-leaderboard .leaderboard-item');

    playerRows.forEach((row, index) => {
      if (index >= 10) return; // Only top 10

      try {
        const name = row.querySelector('.player-name, .participant-name')?.textContent.trim() || null;
        const thPerS = row.querySelector('.hashrate, .th-per-s')?.textContent.trim() || null;
        const percentage = row.querySelector('.share, .percentage')?.textContent.trim() || null;

        if (name) {
          players.push({
            rank: index + 1,
            name,
            th_per_s: thPerS,
            percentage
          });
        }
      } catch (err) {
        console.warn('[MW] Failed to extract player row:', err);
      }
    });

    console.log('[MW] Extracted top players:', players.length);
    return players.length > 0 ? players : null;
  } catch (err) {
    console.error('[MW] Failed to extract top 10 players:', err);
    return null;
  }
}

export function extractTop10Clans(doc = document) {
  try {
    console.log('[MW] Extracting top 10 clans from leaderboard');
    const clans = [];

    // Try to find clan leaderboard items
    const clanRows = doc.querySelectorAll('.leaderboard-clans .leaderboard-item, .clans-leaderboard .leaderboard-item');

    clanRows.forEach((row, index) => {
      if (index >= 10) return; // Only top 10

      try {
        const name = row.querySelector('.clan-name, .participant-name')?.textContent.trim() || null;
        const thPerS = row.querySelector('.hashrate, .th-per-s')?.textContent.trim() || null;
        const percentage = row.querySelector('.share, .percentage')?.textContent.trim() || null;

        if (name) {
          clans.push({
            rank: index + 1,
            name,
            th_per_s: thPerS,
            percentage
          });
        }
      } catch (err) {
        console.warn('[MW] Failed to extract clan row:', err);
      }
    });

    console.log('[MW] Extracted top clans:', clans.length);
    return clans.length > 0 ? clans : null;
  } catch (err) {
    console.error('[MW] Failed to extract top 10 clans:', err);
    return null;
  }
}

// Wait for the "Continue" button to appear in the round finished popup
// This ensures all data is fully loaded before extraction
export async function waitForRoundFinishedComplete(doc = document, maxWaitMs = 10000) {
  const startTime = Date.now();

  while (Date.now() - startTime < maxWaitMs) {
    const panel = doc.querySelector('.modal-round-finished');
    if (!panel) {
      console.log('[MW] Round finished popup not found, waiting...');
      await new Promise(resolve => setTimeout(resolve, 500));
      continue;
    }

    // Check if the popup is still showing "Determining the winners..." message
    const modalBody = panel.querySelector('.modal-body');
    if (modalBody) {
      const bodyText = modalBody.textContent || '';
      if (bodyText.includes('Determining the winners')) {
        console.log('[MW] Still determining winners, waiting...');
        await new Promise(resolve => setTimeout(resolve, 500));
        continue;
      }
    }

    // Check if we have actual winner data (participant info)
    const hasWinnerData = panel.querySelector('.modal-body .participant-info');
    if (hasWinnerData) {
      console.log('[MW] Winner data found, round data is complete');
      return panel;
    }

    // Fallback: Look for the continue button - various possible selectors
    const continueBtn = panel.querySelector('.btn-game-green, button[class*="continue"], .modal-footer button, .modal-actions button');
    if (continueBtn && continueBtn.textContent.trim().length > 0) {
      console.log('[MW] Continue button found, round data is complete');
      return panel;
    }

    console.log('[MW] Waiting for winner data to appear...');
    await new Promise(resolve => setTimeout(resolve, 500));
  }

  console.warn('[MW] Timeout waiting for round finished popup to complete');
  return null;
}

export function extractRoundFinishedData(doc = document) {
  const panel = doc.querySelector('.modal-round-finished');
  if (!panel) {
    console.log('[MW] Round finished popup not found');
    return null;
  }

  console.log('[MW] Extracting data from round finished popup');

  const selectors = {
    roundId: 'a.miner-wars-main__info--left span:nth-child(2)',
    multiplier: '.miner-wars-main__info--left .miner-wars-main__multiplier span',
    timer: '.miner-wars-main__timer',
    winningClan: '.modal-body .participant-info .participant-info__main > p',
    winningPlayer: '.modal-body .participant-info ~ .participant-info .participant-info__main > p',
    rewardFund: '.modal-card-inner .btn-game-green',
    // Extended selectors for comprehensive data
    clanThPerS: '.modal-body .participant-info .participant-info__main .participant-info__hashrate',
    clanPercentage: '.modal-body .participant-info .participant-info__main .participant-info__share',
    playerThPerS: '.modal-body .participant-info ~ .participant-info .participant-info__main .participant-info__hashrate',
    playerPercentage: '.modal-body .participant-info ~ .participant-info .participant-info__main .participant-info__share',
    playerMinebox: '.modal-body .participant-info ~ .participant-info .participant-info__main .participant-info__minebox',
    playerReward: '.modal-body .participant-info ~ .participant-info .participant-info__reward'
  };

  const roundId = panel.querySelector(selectors.roundId)?.textContent.trim() || null;
  const multiplier = panel.querySelector(selectors.multiplier)?.textContent.trim() || null;
  const timer = panel.querySelector(selectors.timer)?.textContent.trim() || null;
  const winningClan = panel.querySelector(selectors.winningClan)?.textContent.trim() || null;
  const winningPlayer = panel.querySelector(selectors.winningPlayer)?.textContent.trim() || null;
  const rewardFund = panel.querySelector(selectors.rewardFund)?.textContent.trim() || null;

  // Extract additional data
  const clanThPerS = panel.querySelector(selectors.clanThPerS)?.textContent.trim() || null;
  const clanPercentage = panel.querySelector(selectors.clanPercentage)?.textContent.trim() || null;
  const playerThPerS = panel.querySelector(selectors.playerThPerS)?.textContent.trim() || null;
  const playerPercentage = panel.querySelector(selectors.playerPercentage)?.textContent.trim() || null;
  const playerMinebox = panel.querySelector(selectors.playerMinebox)?.textContent.trim() || null;
  const playerReward = panel.querySelector(selectors.playerReward)?.textContent.trim() || null;

  const data = {
    block_id: roundId,
    multiplier: multiplier,
    round_time: timer,
    clan_name: winningClan,
    winner_player_name: winningPlayer,
    send_reward_fund: rewardFund,
    clan_th_per_s: clanThPerS,
    clan_percentage: clanPercentage,
    player_th_per_s: playerThPerS,
    player_percentage: playerPercentage,
    player_minebox: playerMinebox,
    winner_reward_gmt: playerReward,
    time_round_finished: new Date().toISOString()
  };

  console.log('[MW] Extracted round finished data:', data);
  return data;
}

export function setupLiveHooks({ onLiveData, onRoundFinished, onBoostEvent } = {}) {
  if (typeof window === 'undefined') return () => {};
  const listeners = [];

  function handleMessage(event) {
    if (!event?.data) return;
    const { type, payload } = event.data;

    // Handle MW WebSocket events
    if (type === 'MW_WS_EVENT' && payload) {
      const [eventName, eventData] = payload;
      console.log('[MW] WS Event:', eventName, eventData);

      // Forward live data updates
      if (onLiveData && eventData) {
        onLiveData(eventData);
      }
    }

    // Handle round events
    if (type === 'MW_ROUND_EVENT' && payload) {
      console.log('[MW] Round event:', payload.name, payload.data);

      if (payload.name === 'roundEnded' && onRoundFinished) {
        onRoundFinished(payload.data);
      }

      if (payload.name === 'roundOpened' && onLiveData) {
        onLiveData(payload.data);
      }
    }

    // Handle ability/boost usage
    if (type === 'MW_ABILITY_USAGE' && onBoostEvent && payload) {
      onBoostEvent(payload);
    }

    // Legacy support for old event names
    if (type === 'liveData' && onLiveData) onLiveData(payload);
    if (type === 'roundFinished' && onRoundFinished) onRoundFinished(payload);
    if (type === 'boostUsage' && onBoostEvent) onBoostEvent(payload);
  }

  window.addEventListener('message', handleMessage);
  listeners.push(() => window.removeEventListener('message', handleMessage));

  return () => {
    listeners.forEach((unsub) => unsub());
  };
}
