document.addEventListener("DOMContentLoaded", async function () {
  
  /************************************************************
   * 0) Previous Group Mode + countdown
   ************************************************************/
  let previousGroupModeActive  = false;  // Are we currently displaying previous group?
  let previousGroupUsed        = false;  // Have we *ever* used previous group data yet?
  let prevGroupTimeoutId       = null;   // for the 30s setTimeout
  let prevGroupCountdownInt    = null;   // for the 1s countdown
  let prevGroupCountdown       = 0;      // 30s integer

  // Interval ID for the normal refresh loop
  let refreshIntervalId        = null;

  /************************************************************
   * 1) Minimal CSS in JS
   ************************************************************/
  const styleEl = document.createElement("style");
  styleEl.type = "text/css";
  styleEl.textContent = `
    .protest-icon-warning {
      color: #ffc107; /* open protest icon color */
      margin-left: 5px;
    }
    .protest-icon-success {
      color: #28a745; /* accepted protest icon color */
      margin-left: 5px;
    }
    .scoreboard-table__row_highlight {
      background-color: rgba(209,236,241, 0.3);
    }
    .scoreboard-footer-countdown {
      font-size: 1.1em;
      font-weight: bold;
      color: #ff0000;
      margin-left: 20px;
    }
  `;
  document.head.appendChild(styleEl);

  /************************************************************
   * 2) Grab DOM elements
   ************************************************************/
  const clockElement        = document.getElementById("clock");
  const scoreboardHeader    = document.getElementById("scoreboard-header");
  const scoreboardTableHead = document.getElementById("scoreboard-table-head");
  const scoreboardTableBody = document.getElementById("scoreboard-table-body");
  const scoreboardFooter    = document.getElementById("scoreboard-footer");
  const infoPanelContainer  = document.getElementById("info-panel-container");

  // Row references for partial updates
  const rowMap = {};

  /************************************************************
   * 3) Dynamic clock in corner
   ************************************************************/
  if (clockElement) {
    function updateClock() {
      const now = new Date();
      clockElement.textContent = now.toLocaleTimeString([], { hour12: false });
    }
    setInterval(updateClock, 1000);
    updateClock();
  }

  /************************************************************
   * 4) Read competitionCode from URL
   ************************************************************/
  const urlParams       = new URLSearchParams(window.location.search);
  const competitionCode = urlParams.get("competitionCode");
  if (!competitionCode) {
    console.error("No competition code in URL!");
    scoreboardHeader.innerHTML = "<h2>Error: No competition code provided.</h2>";
    return;
  }

  /************************************************************
   * 5) Protest statuses
   ************************************************************/
  let protestStatusByRun = {};

  /************************************************************
   * 6) Bearer token & helpers
   ************************************************************/
  const STATIC_BEARER_TOKEN = "50afb255cfa3a36834e0a51185b1eb09";

  function getHeaders(isJson = true) {
    const baseHeaders = isJson ? { "Content-Type": "application/json" } : {};
    baseHeaders["Authorization"] = `Bearer ${STATIC_BEARER_TOKEN}`;
    return baseHeaders;
  }

  function handleNotOkResponse(resp) {
    console.error(`API responded with ${resp.status}: ${resp.statusText}`);
    alert("Invalid or expired token. Redirecting...");
    localStorage.removeItem("user");
    window.location.href = "index.html";
  }

  function checkSessionError(data) {
    if (!data) return;
    const errStr = String(data.error || "").toLowerCase();
    if (errStr.includes("invalid") || errStr.includes("session") || errStr.includes("expired")) {
      alert("Invalid or expired token. Redirecting...");
      localStorage.removeItem("user");
      window.location.href = "index.html";
    }
  }

  /************************************************************
   * 7) Main refresh loop
   ************************************************************/
  function startRefreshLoop() {
    refreshScoreboard();
    refreshIntervalId = setInterval(refreshScoreboard, 5000);
  }

  function stopRefreshLoop() {
    if (refreshIntervalId) {
      clearInterval(refreshIntervalId);
      refreshIntervalId = null;
    }
  }

  // Kick off once loaded
  startRefreshLoop();

  function refreshScoreboard() {
    // If we're in previous group mode, skip
    if (previousGroupModeActive) {
      console.log("[DEBUG] skip refresh => previous group mode active");
      return;
    }
    fetchProtestStatuses()
      .then((statusMap) => {
        protestStatusByRun = statusMap;
        return fetchScoreboardData(competitionCode);
      })
      .catch((err) => console.error("Error refreshScoreboard:", err));
  }

  /************************************************************
   * 8) fetchScoreboardData => parse => decide which group
   ************************************************************/
  function fetchScoreboardData(code) {
    return fetch(
      `${API_BASE_URL}?api=results&competitionCode=${encodeURIComponent(code)}&public=true`,
      {
        method: "GET",
        headers: getHeaders(false),
      }
    )
      .then((resp) => {
        if (!resp.ok) {
          handleNotOkResponse(resp);
          return null;
        }
        return resp.json();
      })
      .then((json) => {
        if (!json) return;
        checkSessionError(json);

        const data = json.data;
        if (!data || !data.success) {
          console.error("Invalid scoreboard data:", json);
          return;
        }

        // ----------------------------------------
        // DO THE PREVIOUS GROUP TIME CHECK *NOW*
        // ----------------------------------------
        if (
          data.previous_group_data &&
          data.previous_group_data.previous_group &&
          !previousGroupModeActive &&
          !previousGroupUsed
        ) {
          const pg = data.previous_group_data.previous_group;
          const lastTimeStr = pg.last_run_timestamp; 
          if (lastTimeStr) {
            // parse as UTC
            const isoString = lastTimeStr.replace(" ", "T") + "Z";
            const lastMs    = Date.parse(isoString);
            if (!isNaN(lastMs)) {
              const nowMs  = Date.now() + 7200000;
              const diffMs = nowMs - lastMs;
              console.log("[DEBUG] previous_group ", nowMs, " - last_run_timestamp =", lastTimeStr, "=> diffMs =", diffMs);
              // If < 30s => show the previous group
              if (diffMs < 30000) {
                console.log("[DEBUG] Show previous group for 30s");
                showPreviousGroupMode(data.previous_group_data);
                // STOP => do not render active group
                return;
              }
            }
          }
        }

        // If we get here => show active group
        const scoreboardData = {
          scoreboardGroup: data.active_group,
          scoreboardRuns: data.runs,
        };
        updateScoreboard(scoreboardData, data.active_athlete);
      })
      .catch((err) => console.error("Error fetchScoreboardData:", err));
  }

  // ----------------------------------------------------------
  // showPreviousGroupMode => stops auto refresh, shows 30s countdown
  // ----------------------------------------------------------
  function showPreviousGroupMode(prevData) {
    previousGroupModeActive = true;
    //previousGroupUsed       = true;

    // stop auto updates
    stopRefreshLoop();

    // render scoreboard with the previous group
    const { previous_group, runs, previous_athlete } = prevData;
    updateScoreboard({ scoreboardGroup: previous_group, scoreboardRuns: runs }, previous_athlete);

    // Start 30s countdown
    prevGroupCountdown = 30;
    scoreboardFooter.innerHTML += `
      <span id="countdown-timer" class="scoreboard-footer-countdown">
        30s remaining...
      </span>
    `;
    prevGroupCountdownInt = setInterval(() => {
      prevGroupCountdown--;
      if (prevGroupCountdown <= 0) {
        clearInterval(prevGroupCountdownInt);
      }
      const timerEl = document.getElementById("countdown-timer");
      if (timerEl) {
        timerEl.textContent = `${prevGroupCountdown}s remaining...`;
      }
    }, 1000);

    // after 30s => revert to normal mode
    prevGroupTimeoutId = setTimeout(() => {
      console.log("[DEBUG] 30s up => switch to active group");
      previousGroupModeActive = false;
      clearInterval(prevGroupCountdownInt);
      const timerEl = document.getElementById("countdown-timer");
      if (timerEl && timerEl.parentNode) {
        timerEl.parentNode.removeChild(timerEl);
      }
      // resume normal refresh => fetch new data => active group
      startRefreshLoop();
    }, 30000);
  }

  /************************************************************
   * 9) updateScoreboard => standard rendering
   ************************************************************/
  function updateScoreboard({ scoreboardGroup, scoreboardRuns }, activeAthlete) {
    // Clear old rows
    for (const runId in rowMap) {
      const oldDiv = rowMap[runId];
      if (oldDiv && oldDiv.parentNode === scoreboardTableBody) {
        scoreboardTableBody.removeChild(oldDiv);
      }
      delete rowMap[runId];
    }

    // Scoreboard header
    scoreboardHeader.innerHTML = `
      <h2>${(scoreboardGroup.competitionName || "").toUpperCase()}</h2>
      <h1>${(scoreboardGroup.group_name || "").toUpperCase()}</h1>
      <h2>${(scoreboardGroup.event_name || "").toUpperCase()} - GROUP ${scoreboardGroup.group}</h2>
    `;

    // Table head
    scoreboardTableHead.innerHTML = `
      <div class="scoreboard-table__col"></div>
      <div class="scoreboard-table__col">RANKING</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">SURNAME</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">NAME</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">BIRTHYEAR</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">COUNTRY</div>
      <div class="scoreboard-table__col">SCORE 1</div>
      <div class="scoreboard-table__col">SCORE 2</div>
      <div class="scoreboard-table__col"></div>
    `;

    // Identify "next" athlete highlight?
    let activeRunId = activeAthlete?.run_id || -1;
    const nextObj = findNextRun(scoreboardRuns, activeRunId);
    const nextAthleteId = nextObj?.athlete_id || null;

    // DSQ SHIFT LOGIC (sort out DSQ rows last)
    const nonDSQ = [];
    const dsqArr = [];
    scoreboardRuns.forEach((ath) => {
      const hasDSQ = ath.runs.some((r) => r.status === 4);
      if (hasDSQ) dsqArr.push(ath);
      else        nonDSQ.push(ath);
    });

    nonDSQ.sort((a, b) => a.placement - b.placement);
    nonDSQ.forEach((item, idx) => { item.placement = idx + 1; });
    dsqArr.forEach((item) => { item.placement = 9999; });
    const finalSorted = [...nonDSQ, ...dsqArr];

    // Build row for each athlete
    finalSorted.forEach((ath) => {
      const rowKey = `group_${scoreboardGroup.schedule_id}_athlete_${ath.athlete_id}`;
      const rowDiv = document.createElement("div");
      rowDiv.className = "scoreboard-table__row";

      const isActive = (ath.athlete_id === activeAthlete?.id);
      const isNext   = (ath.athlete_id === nextAthleteId);

      updateRowDiv(rowDiv, ath, scoreboardGroup, isActive, isNext);
      scoreboardTableBody.appendChild(rowDiv);
      rowMap[rowKey] = rowDiv;
    });

    // Footer standard
    scoreboardFooter.innerHTML = `
      <div class="item">FRS = First Run Scores</div>
      <div class="item">
        <img src="images/qualified.svg" width="14" height="14" alt=""> = Qualified
      </div>
      <div class="item">Top ${scoreboardGroup.qualify} in the next round</div>
    `;

    // Info panel => active athlete
    if (activeAthlete) {
      updateInfoPanelAthlete(activeAthlete);
    }
  }

  function findNextRun(athletes, activeRunId) {
    const allRuns = athletes.flatMap((ath) =>
      ath.runs.map((r) => ({
        ...r,
        athlete_id: ath.athlete_id,
        athlete_name: ath.athlete_name,
      }))
    );
    const future = allRuns.filter((r) => r.status === 0 && r.run_id > activeRunId);
    future.sort((a, b) => a.run_id - b.run_id);
    return future[0] || null;
  }

  /************************************************************
   * 10) Build scoreboard row
   ************************************************************/
  function updateRowDiv(rowDiv, athlete, scoreboardGroup, isActive, isNext) {
    const isQualified =
      athlete.placement <= (scoreboardGroup.qualify || 0) &&
      ((athlete.runs[0]?.score ?? 0) > 0 || (athlete.runs[1]?.score ?? 0) > 0);

    if (isActive) {
      rowDiv.classList.add("scoreboard-table__row_highlight");
    }

    const nextCell = isNext ? `<div class="scoreboard-table__col scoreboard-table__col_next"></div>` 
                            : `<div class="scoreboard-table__col"></div>`;

    // name: firstName + lastName from athlete.athlete_name
    const [firstName = "", ...rest] = (athlete.athlete_name || "").trim().split(/\s+/);
    const lastName = rest.join(" ");

    let surnameCell = lastName;
    if (athlete.bib) {
      surnameCell += ` <span style="font-size:0.7em;" class="text-muted">(${athlete.bib})</span>`;
    }

    const isDSQ    = (athlete.placement === 9999);
    const rankCell = isDSQ ? "DSQ" : athlete.placement;

    rowDiv.innerHTML = `
      ${nextCell}
      <div class="scoreboard-table__col scoreboard-table__col_place">${rankCell}</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">${surnameCell}</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">${firstName}</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">${athlete.birthyear}</div>
      <div class="scoreboard-table__col scoreboard-table__col_accent">${athlete.country}</div>
      <div class="scoreboard-table__col">${buildProtestAwareLabel(athlete.runs[0])}</div>
      <div class="scoreboard-table__col">${buildProtestAwareLabel(athlete.runs[1])}</div>
      <div class="scoreboard-table__col">
        ${ isQualified ? `<img src="images/qualified.svg" alt="Qualified">` : "" }
      </div>
    `;
  }

  /************************************************************
   * 11) Protest logic
   ************************************************************/
  function buildProtestAwareLabel(run) {
    if (!run) return "";
    const base = getScoreLabel(run);
    if (run.status === 1) {
      return base; // published => no protest icon
    }
    const pStatus = protestStatusByRun[run.run_id];
    if (pStatus === 0) {
      return `${base} <i class="bi bi-exclamation-triangle-fill protest-icon-warning"></i>`;
    } else if (pStatus === 1) {
      return `${base} <i class="bi bi-check-circle-fill protest-icon-success"></i>`;
    }
    return base;
  }

  function getScoreLabel(run) {
    switch (run?.status) {
      case 2: return "FRS";
      case 3: return "DNS";
      case 4: return "DSQ";
      default:
        return run?.score ?? "";
    }
  }

  /************************************************************
   * 12) Info panel => active athlete
   ************************************************************/
  function updateInfoPanelAthlete(athlete) {
    if (!athlete) {
      infoPanelContainer.innerHTML = "<p>No athlete data.</p>";
      return;
    }

    const athleteId = athlete.athlete_id || athlete.id || "default";
    let name = athlete.name || athlete.athlete_name || "Unknown Athlete";
    if (athlete.bib) {
      name += ` <span style="font-size:0.7em;" class="text-muted">(${athlete.bib})</span>`;
    }

    const defaultPic = "images/athletes/default.png";
    const athletePic = `images/athletes/${athleteId}.png`;

    checkImageExistence(athletePic, (exists) => {
      const imgUrl = exists ? athletePic : defaultPic;
      infoPanelContainer.innerHTML = `
        <div id="player-info" class="player-info">
          <div class="player-info__top">
            <img class="player-info__photo" src="${imgUrl}" alt="">
            <div class="player-info__place">#${athlete?.placement || "-"}</div>
          </div>
          <div class="player-info__name">${name}</div>
          <div class="player-info__country">${athlete?.country_name || athlete?.country || ""}</div>
          <h3>SPONSORS</h3>
          <p>${athlete?.sponsors || "N/A"}</p>
          <h3>HOMECABLE</h3>
          <p>${athlete?.homecable || "N/A"}</p>
        </div>
      `;
    });
  }

  /************************************************************
   * 13) Check if image exists (local file)
   ************************************************************/
  function checkImageExistence(path, cb) {
    const img = new Image();
    img.onload  = () => cb(true);
    img.onerror = () => cb(false);
    img.src     = path;
  }

  /************************************************************
   * 14) fetchProtestStatuses
   ************************************************************/
  function fetchProtestStatuses() {
    return fetch(
      `${API_BASE_URL}?api=protests&competitionCode=${encodeURIComponent(competitionCode)}`,
      {
        method: "GET",
        headers: getHeaders(false),
      }
    )
    .then((resp) => {
      if (!resp.ok) {
        handleNotOkResponse(resp);
        return {};
      }
      return resp.json();
    })
    .then((json) => {
      if (!json) return {};
      checkSessionError(json);
      if (!json.success) {
        console.warn("Failed to fetch protests:", json.error);
        return {};
      }
      const arr = json.data || [];
      const map = {};
      arr.forEach((p) => {
        map[p.run_id] = p.status;
      });
      return map;
    })
    .catch((err) => {
      console.error("Error fetching protests:", err);
      return {};
    });
  }
});