let selectedMonday;
let currentAccountForModal = null;
let currentUserForModal = null;


const SESSION_EXPIRY_HOURS = 24;
const SESSION_CHECK_INTERVAL = 10 * 60 * 1000; // every 10 min

let isCheckingSession = false;

async function checkSession() {
  if (isCheckingSession) return;  // 🚫 prevent double clicks
  isCheckingSession = true;

  const btn = document.getElementById("checkSessionBtn");
  if (btn) {
    btn.disabled = true;
    btn.textContent = "Checking...";
  }

  try {
    const res = await fetch("https://stephieluv.com/manager/scraped/not-work/test.php");
    const data = await res.json();

    let status = data.message?.includes("SessionID looks OK") ? "valid" : "invalid";
    await saveSessionStatus(status);
    renderSessionStatus(status);
  } catch {
    await saveSessionStatus("invalid");
    renderSessionStatus("invalid");
  } finally {
    if (btn) {
      btn.disabled = false;
      btn.textContent = "Check Session";
    }
    isCheckingSession = false; // 🔓 unlock after done
  }
}

function renderSessionStatus(status) {
  const statusSpan = document.getElementById("sessionStatus");

  if (status === "valid") {
    statusSpan.innerHTML = `SessionID OK <span style="color:limegreen;">●</span>`;
  } else if (status === "invalid") {
    statusSpan.innerHTML = `SessionID invalid <span style="color:red;">●</span>`;
  } else {
    statusSpan.innerHTML = `SessionID unknown <span style="color:gray;">●</span>`;
  }
}


async function saveSessionStatus(status) {
  await fetch("backend.php?action=saveSessionStatus", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      status: status,
      timestamp: new Date().toISOString()
    })
  });
}

async function loadSessionStatus() {
  const res = await fetch("backend.php?action=getSessionStatus");
  const data = await res.json();

  // Expiry check
  if (data.timestamp) {
    const lastCheck = new Date(data.timestamp);
    const hoursSince = (Date.now() - lastCheck.getTime()) / (1000 * 60 * 60);

    if (hoursSince >= SESSION_EXPIRY_HOURS) {
      // Too old → re-check now
      await checkSession();
      return;
    }
  }

  renderSessionStatus(data.status);
}

// Auto check every 10 minutes
setInterval(async () => {
  const res = await fetch("backend.php?action=getSessionStatus");
  const data = await res.json();

  if (data.timestamp) {
    const lastCheck = new Date(data.timestamp);
    const hoursSince = (Date.now() - lastCheck.getTime()) / (1000 * 60 * 60);

    if (hoursSince >= SESSION_EXPIRY_HOURS) {
      await checkSession();
    } else {
      renderSessionStatus(data.status);
    }
  } else {
    await checkSession();
  }
}, SESSION_CHECK_INTERVAL);

// Init
document.addEventListener("DOMContentLoaded", loadSessionStatus);
document.getElementById("checkSessionBtn").addEventListener("click", checkSession);



const modalCheckBtn = document.getElementById("modalCheckAccountBtn");

let isCheckingAccount = false;

modalCheckBtn.addEventListener("click", async () => {
  if (isCheckingAccount) return;   // 🚫 prevent double clicks
  isCheckingAccount = true;

  if (!currentAccountForModal) {
    alert("⚠️ No account is currently selected.");
    isCheckingAccount = false;
    return;
  }

  const accountName = currentAccountForModal.name;
  const originalText = modalCheckBtn.textContent;

  // 🔒 Lock button
  modalCheckBtn.disabled = true;
  modalCheckBtn.textContent = "Checking...";

  try {
    const res = await fetch(`scraped/getuser.php?username=${encodeURIComponent(accountName)}`);
    const data = await res.json();

    if (data.error) {
      if (data.error.includes("getuser.php failed to return a valid userID")) {
        alert(`⚠️ The account "${accountName}" is deleted or the username does not exist.`);
        markAccountBanned(accountName);
      } 
      else if (
        data.error.includes("User not found") || 
        data.error.includes("private") || 
        data.error.includes("banned")
      ) {
        alert(`⚠️ Account "${accountName}" does not exist or is private/banned.`);
        markAccountBanned(accountName);
      } 
      else if (data.error.includes("Session expired")) {
        alert("❌ Session expired. Please update your sessionid.txt");
      } 
      else {
        alert(`⚠️ Error checking account: ${data.error}`);
      }
    } 
    else if (data.userID) {
      alert(`✅ Account "${accountName}" is active. UserID: ${data.userID}`);
    } 
    else {
      alert(`⚠️ Unexpected response while checking "${accountName}".`);
      console.log("Check Account raw:", data);
    }
  } catch (err) {
    console.error("Check Account failed:", err);
    alert("❌ Failed to check account. Network or server error.");
  } finally {
    // 🔓 Restore button
    modalCheckBtn.disabled = false;
    modalCheckBtn.textContent = originalText;
    isCheckingAccount = false;
  }
});

async function markAccountBanned(accountName) {
  // --- Save banned status in stored.txt via backend ---
  try {
    const res = await fetch("backend.php?action=update_banned", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ accountName, banned: true })
    });
    const result = await res.json();
    console.log("✅ Stored banned status:", result);

    // ✅ Also persist banned flag in local state so it survives next save
    try {
      for (const u of state.users) {
        const acc = u.accounts.find(a => a.name === accountName);
        if (acc) {
          acc.banned = true; // mark it in memory
        }
      }
      await saveStateToServer(); // push updated state back to backend
    } catch (e) {
      console.warn("⚠️ Could not persist local banned flag to stored.txt", e);
    }
  } catch (err) {
    console.error("❌ Failed to save banned status:", err);
  }

  // --- Update DOM for this account ---
  const accountItem = [...document.querySelectorAll(".account-item")]
    .find(el => el.querySelector(".accountName")?.textContent.trim() === accountName);

  if (!accountItem) return;

  // 1. Strike-through + red on account name
  const nameEl = accountItem.querySelector(".accountName");
  if (nameEl) {
    nameEl.style.textDecoration = "line-through";
    nameEl.style.textDecorationColor = "red";
    nameEl.style.textDecorationThickness = "2px";
    nameEl.style.color = "red";
  }

  // 2. Disable refresh button
  const refreshBtn = accountItem.querySelector("button[title='Refresh day boxes']");
  if (refreshBtn) {
    refreshBtn.disabled = true;
    refreshBtn.style.opacity = "0.5";
    refreshBtn.style.cursor = "not-allowed";
  }

  // 3. Disable clicking on day boxes but keep tooltips
  accountItem.querySelectorAll(".day-box").forEach(box => {
    box.addEventListener("click", (e) => {
      e.preventDefault();
      e.stopPropagation();
      console.log("Click blocked on day box (banned account).");
    }, true);

    box.classList.add("cursor-not-allowed", "opacity-70");
  });
}

async function fetchScraper(url, loader = null) {
  try {
    const res = await fetch(url);
    const data = await res.json();

    // 🚨 Handle API error responses
    if (data.error) {
      if (data.error.includes("getuser.php failed to return a valid userID")) {
        alert("⚠️ The account is deleted or the username does not exist.");
      } else if (data.error.includes("execution error")) {
        alert("❌ Scraper execution error. Try again later.");
      } else {
        alert("⚠️ Scraper error: " + data.error);
      }

      if (loader) loader.style.display = "none";
      await saveSessionStatus("invalid");
      renderSessionStatus("invalid");
      return null; // stop further
    }

    // 🚨 Handle session invalid
    if (
      data.status === "session_invalid" ||
      (data.raw_response &&
        data.raw_response.errors &&
        data.raw_response.errors[0]?.message === "execution error")
    ) {
      alert("❌ SessionID is invalid. Please re-login.");

      await saveSessionStatus("invalid");
      renderSessionStatus("invalid");
      if (loader) loader.style.display = "none";
      return null;
    }

    // ✅ If posts exist → session is valid
    if (data && data.posts) {
      await saveSessionStatus("valid");
      renderSessionStatus("valid");
    }

    return data;
  } catch (err) {
    console.error("Error calling scraper:", err);

    if (loader) loader.style.display = "none";
    return null; // no duplicate alerts here
  }
}


Object.defineProperty(window, "selectedMonday", {
  set(value) {
    console.trace("TRACE: selectedMonday changed to:", value.toISOString().split("T")[0]);
    this._selectedMonday = value;
  },
  get() {
    return this._selectedMonday;
  }
});

const byId = (id) => document.getElementById(id);
const uid = () => Math.random().toString(36).slice(2);

let state = { users: [] }; // fetched from PHP
let expandedUsers = new Set(); // Track which user sections are expanded

const countryTimezones = {
  "Nigeria": "Africa/Lagos",
  "Romania": "Europe/Bucharest",
  "USA": "America/New_York", // you can adjust to preferred US timezone
  "UK": "Europe/London",
  "India": "Asia/Kolkata",
  "Thailand": "Asia/Bangkok",
  "Egypt": "Africa/Cairo",
  "UAE": "Asia/Dubai",
    "Australia": "Australia/Sydney" // ✅ Added Australia
};

const usersContainer = byId("usersContainer");
const userRowTpl = byId("userRowTpl");
const accountItemTpl = byId("accountItemTpl");
const searchBox = byId("searchBox");

const dayNames = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

// --- Load state from PHP ---
async function loadStateFromServer() {
  const res = await fetch("backend.php?action=load");
  state = await res.json();
  render();
}

// --- Save state to PHP ---
async function saveStateToServer() {
  await fetch("backend.php?action=save", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(state)
  });
}

// --- Render UI ---
async function render(filter = "") {
  usersContainer.innerHTML = "";
  const q = filter.trim().toLowerCase();

  // ✅ Fetch results ONCE from backend.php
const resultsMap = state.results || {};

  state.users.forEach((user) => {
    const userNameMatch = user.name.toLowerCase().includes(q);
    const accountsMatch = user.accounts.some((a) => a.name.toLowerCase().includes(q));
    if (q && !(userNameMatch || accountsMatch)) return;

    const node = userRowTpl.content.cloneNode(true);
    const row = node.querySelector("div.border");
    const nameEl = row.querySelector(".userName");
    const countEl = row.querySelector(".accountsCount");
    const accountsWrap = row.querySelector(".accounts");
    const ul = accountsWrap.querySelector("ul");

nameEl.textContent = user.name;
countEl.textContent = `(${user.accounts.length} accounts)`;

// --- Create Country Selector for User ---
const countrySelect = document.createElement("select");
countrySelect.className = "rounded-lg border border-gray-300 px-2 py-1 text-sm ml-2";
countrySelect.innerHTML = `
  <option value="Nigeria">Nigeria</option>
  <option value="Romania">Romania</option>
  <option value="USA">USA</option>
  <option value="UK">UK</option>
  <option value="India">India</option>
  <option value="Thailand">Thailand</option>
  <option value="Egypt">Egypt</option>
  <option value="UAE">UAE</option>
    <option value="Australia">Australia</option> <!-- ✅ Add this line -->
`;

// Default to Nigeria if country not set
countrySelect.value = user.country || "Nigeria";

// 🔒 Lock dropdown if user already has accounts
countrySelect.disabled = user.accounts.length > 0;
if (countrySelect.disabled) {
  countrySelect.title = "Cannot change country while there are accounts under this user.";
} else {
  countrySelect.title = "Select a country for this user.";
}

// Save when changed
countrySelect.addEventListener("change", async (e) => {
  if (countrySelect.disabled) {
    alert("❌ You cannot change the country while this user has accounts. Remove all accounts first.");
    e.preventDefault();
    countrySelect.value = user.country; // Reset to the original country
    return;
  }

  user.country = e.target.value;
  await saveStateToServer();

  // ✅ Automatically refresh yellow/grey statuses for this user
  await updateYellowDays(user);

  console.log(`Country changed to ${user.country} for user ${user.name}. Status refreshed.`);
});


// --- Wrap Country Selector and Refresh Button ---
const wrapper = document.createElement("div");
wrapper.style.display = "flex";
wrapper.style.alignItems = "center";
wrapper.style.gap = "8px";

// Create refresh button
const refreshBtn = document.createElement("button");
refreshBtn.innerHTML = "⟳"; // refresh symbol
refreshBtn.title = "Refresh days";
refreshBtn.className = "px-2 py-0 border rounded text-gray-600 hover:bg-gray-200";

// Create clock element
const clock = document.createElement("span");
clock.className = "user-clock"; // uses our CSS
clock.textContent = "--:--"; // default placeholder


// When clicked, only refresh this user's yellow/grey statuses
refreshBtn.addEventListener("click", async () => {
  await updateYellowDays(user); // Pass only this user
  console.log(`Manual refresh done for ${user.name}`);
});

// Add both to wrapper
wrapper.appendChild(countrySelect);
wrapper.appendChild(refreshBtn);
wrapper.appendChild(clock); // add clock here
// Place wrapper after account count
countEl.after(wrapper);

// Start live clock for this user
startUserClock(clock, countrySelect);

    // --- Toggle expand/collapse via arrow button ---
    const toggleBtn = row.querySelector(".toggleBtn");
    toggleBtn.addEventListener("click", (e) => {
      e.stopPropagation();
      accountsWrap.classList.toggle("hidden");

      if (accountsWrap.classList.contains("hidden")) {
        expandedUsers.delete(user.name); // collapsed
      } else {
        expandedUsers.add(user.name); // expanded
      }
      toggleBtn.textContent = accountsWrap.classList.contains("hidden") ? "▸" : "▾";
    });
    
const userNameEl = row.querySelector(".userName");
const accountsCountEl = row.querySelector(".accountsCount");

[userNameEl, accountsCountEl].forEach(el => {
  el.addEventListener("click", (e) => {
    e.stopPropagation();
    toggleBtn.click(); // 🔹 Trigger the toggle button
  });
});
    // Restore expanded state
    if (expandedUsers.has(user.name)) {
      accountsWrap.classList.remove("hidden");
      toggleBtn.textContent = "▾";
    } else {
      accountsWrap.classList.add("hidden");
      toggleBtn.textContent = "▸";
    }

    // --- Add Account ---
    const accountInput = row.querySelector(".accountInput");
row.querySelector(".addAccountBtn").addEventListener("click", async () => {
  let accountName = accountInput.value.trim();
  if (!accountName) {
    accountName = prompt("New account name:");
    if (!accountName) return;
  }

  // Prevent duplicate account names under same user
  if (user.accounts.some(a => a.name.toLowerCase() === accountName.toLowerCase())) {
    alert("Account already exists for this user.");
    return;
  }
  
// ✅ STEP 0: Verify account exists with getuser.php
try {
  const checkRes = await fetch(`scraped/getuser.php?username=${encodeURIComponent(accountName)}`);
  const checkData = await checkRes.json();

  if (checkData.error) {
    if (
      checkData.error.includes("User not found") ||
      checkData.error.includes("private") ||
      checkData.error.includes("banned") ||
      checkData.error.includes("deleted") ||
      checkData.error.includes("getuser.php failed")
    ) {
      alert(`❌ The account "${accountName}" does not exist, is private, banned or deleted. Cannot add.`);
      return; // ⛔ STOP everything
    }
    if (checkData.error.includes("Session expired")) {
      alert("❌ Session expired. Please update your sessionid.txt.");
      return; // ⛔ STOP everything
    }
    if (checkData.error.includes("Folder for username")) {
      // ✅ Ignore this error (folder will be created later)
      console.warn(`⚠️ No folder yet for "${accountName}", continuing with add...`);
    } else {
      alert(`⚠️ Error verifying account "${accountName}": ${checkData.error}`);
      return; // ⛔ STOP everything
    }
  }

  if (!checkData.userID && !checkData.error?.includes("Folder for username")) {
    alert(`❌ Could not verify account "${accountName}".`);
    return; // ⛔ STOP everything
  }

  if (checkData.userID) {
    console.log(`✅ Verified account "${accountName}" exists with userID: ${checkData.userID}`);
  }
} catch (err) {
  console.error("❌ Verification failed:", err);
  alert("❌ Failed to verify account. Network or server error.");
  return; // ⛔ STOP everything
}


  // --- STEP 1: Get currently selected week ---
  console.log("DEBUG Selected Monday when adding account:", selectedMonday.toISOString().split("T")[0]); // <-- Add here

  const weekFolderName = "week-" + formatDate(selectedMonday).replace(" ", "-").toLowerCase();
  const weekKey = selectedMonday.toISOString().split("T")[0];

  // --- STEP 2: Ensure correct folder structure exists on the server ---
  try {
    const resp = await fetch("backend.php?action=checkAndCreateFolders", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        user: user.name,
        weekFolder: weekFolderName,
        account: accountName,
        day: "Monday" // placeholder to ensure all weekdays are generated
      })
    });
    const data = await resp.json();
    if (!data.success) {
      alert(`❌ Failed to create folder structure: ${data.error}`);
      return;
    }
    console.log(`📂 Verified folder structure for ${user.name}/${weekFolderName}/${accountName}`);
  } catch (err) {
    console.error("❌ Error creating folder structure:", err);
    alert("Server error when creating folders. Check console for details.");
    return;
  }

  // --- STEP 3: Prepare 7 days for the selected week ---
  const timezone = countryTimezones[user.country] || "UTC";
  const nowUtc = new Date();

  const nowInCountry = new Date(
    new Intl.DateTimeFormat("en-US", {
      timeZone: timezone,
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false
    }).format(nowUtc)
  );

  const daysInit = {};
  for (let i = 1; i <= 7; i++) {
    const dayDate = new Date(selectedMonday);
    dayDate.setDate(selectedMonday.getDate() + (i - 1));

    const dayStartInCountry = new Date(
      new Intl.DateTimeFormat("en-US", {
        timeZone: timezone,
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false
      }).format(new Date(`${dayDate.toISOString().split("T")[0]}T00:00:00Z`))
    );

    const status = nowInCountry < dayStartInCountry ? "yellow" : "grey";
    daysInit[i] = { status, date: dayDate.toISOString().split("T")[0] };
  }

  // --- STEP 4: Save to stored.txt ---
user.accounts.push({
  id: uid(),
  name: accountName,
  targetPosts: 0,
  vaCharge: 0,
  last_update_refresh: "never used",  // ✅ default value
  banned: false,   // ✅ default not banned
  weeks: { [weekKey]: daysInit }
});


  await saveStateToServer();
  
  // 🔒 Lock the country select because user now has accounts
const thisUserRow = [...document.querySelectorAll(".user-card")]
  .find(row => row.querySelector(".userName").textContent === user.name);

if (thisUserRow) {
  const select = thisUserRow.querySelector("select");
  if (select) {
    select.disabled = true;
    select.title = "Cannot change country while there are accounts under this user.";
  }
}

  // Immediately run yellow/grey verification
  await updateYellowDays(user);

  render(searchBox.value);

  // Keep user section expanded
  if (expandedUsers.has(user.name)) {
    accountsWrap.classList.remove("hidden");
    toggleBtn.textContent = "▾";
  }

  console.log(`✅ Account "${accountName}" added under week "${weekFolderName}"`);
});


    // --- Rename User ---
// --- Rename User (Safe Rename) ---
row.querySelector(".renameUserBtn").addEventListener("click", async (e) => {
  e.stopPropagation();

  const oldName = user.name;
  const newName = prompt("Rename user:", oldName);
  if (!newName || newName.trim() === oldName) return;

  // ✅ Check for duplicate usernames
  if (state.users.some(u => u !== user && u.name.toLowerCase() === newName.toLowerCase())) {
    alert("Another user already has that name.");
    return;
  }

  try {
    // --- 1. Ask backend to rename folder on disk ---
    const resp = await fetch("backend.php?action=renameUserFolder", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        oldUserName: oldName,
        newUserName: newName.trim()
      })
    });

    const data = await resp.json();
    if (!data.success) {
      alert(`❌ Failed to rename folder: ${data.error}`);
      return;
    }

    console.log(`📂 User folder successfully renamed: ${oldName} → ${newName}`);

    // --- 2. Update stored.txt (state) ---
    user.name = newName.trim();
    await saveStateToServer();

    console.log(`✏️ User updated in stored.txt: ${oldName} → ${newName}`);
    render(searchBox.value);

  } catch (err) {
    console.error("❌ Error renaming user:", err);
    alert("Server error while renaming user folder.");
  }
});


    // --- Delete User ---
row.querySelector(".deleteUserBtn").addEventListener("click", async (e) => {
  e.stopPropagation(); // ✅ Now e is defined
  if (!confirm(`Delete user "${user.name}" and ALL its accounts?`)) return;
  state.users = state.users.filter((u) => u !== user);
  await saveStateToServer();
  render(q);
});

    // --- Render Accounts for this User ---
    user.accounts.forEach((account) => {
      if (q && !user.name.toLowerCase().includes(q) && !account.name.toLowerCase().includes(q)) return;

      const item = accountItemTpl.content.cloneNode(true);
        // Account Name
  item.querySelector(".accountName").textContent = account.name;
  console.log("Rendering account:", account.name, "banned?", account.banned);
        // ✅ Auto-mark banned accounts from stored.txt
const isBanned = account.banned === true || account.banned === "true" || account.banned === 1;
console.log("Rendering account:", account.name, "banned?", isBanned);

if (isBanned) {
  setTimeout(() => markAccountBanned(account.name), 0);
}
 // ✅ Create loader dynamically for each account
// ✅ Create Refresh Button + Loader dynamically for each account
const actionsContainer = item.querySelector(".flex.items-center.gap-3");
const settingsBtn = document.createElement("button");
settingsBtn.innerHTML = "⚙️";
settingsBtn.className = "text-gray-700 hover:text-gray-900 transition text-lg font-bold";
settingsBtn.style.cursor = "pointer";
settingsBtn.style.marginLeft = "8px";

actionsContainer.appendChild(settingsBtn);

settingsBtn.addEventListener("click", () => {
  currentAccountForModal = account;
  currentUserForModal = user;

  // Load saved values or default to 0
  document.getElementById("targetPostsInput").value = account.targetPosts ?? 0;
  document.getElementById("vaChargeInput").value = account.vaCharge ?? 0;

  document.getElementById("modalAccountTitle").textContent = `Settings for ${account.name}`;
  document.getElementById("settingsModal").classList.remove("hidden");
});


if (actionsContainer) {
  // --- Refresh Button ---
  const refreshBtn = document.createElement("button");
  refreshBtn.innerHTML = "⟳"; // refresh symbol
  refreshBtn.title = "Refresh day boxes";
  refreshBtn.className = "text-blue-600 hover:text-blue-800 transition text-lg font-bold";
  refreshBtn.style.cursor = "pointer";
  
  // --- Info Button ---
const infoBtn = document.createElement("button");
infoBtn.innerHTML = "ℹ️"; // info icon
infoBtn.className = "info-btn text-blue-500 hover:text-blue-700 transition text-lg font-bold";
infoBtn.style.cursor = "pointer";
infoBtn.style.marginLeft = "8px"; // small space between refresh and info
infoBtn.style.width = "32px";
infoBtn.style.height = "32px";
infoBtn.style.display = "flex";
infoBtn.style.alignItems = "center";
infoBtn.style.justifyContent = "center";
infoBtn.style.padding = "0"; // prevent extra spacing

// --- Create the info box container ---
const infoBox = document.createElement("div");
infoBox.className = "account-info-box absolute bg-white shadow-lg border border-gray-300 rounded-lg p-4 text-sm w-64";
infoBox.style.position = "fixed";
infoBox.style.zIndex = "99999"; // <-- VERY IMPORTANT
infoBox.style.display = "none";
infoBox.style.maxHeight = "none";   // Allow height to grow naturally
infoBox.style.overflowY = "visible"; // No scroll bar
infoBox.style.transition = "opacity 0.3s ease";

const settingsBtn = document.createElement("button");
settingsBtn.innerHTML = "⚙️"; 
settingsBtn.className = "text-gray-700 hover:text-gray-900 transition text-lg font-bold";
settingsBtn.style.cursor = "pointer";
settingsBtn.style.marginLeft = "8px";

  // Action when clicked
refreshBtn.addEventListener("click", async (e) => {
  e.stopPropagation();

  console.log(`🔄 Manual refresh clicked for account: ${account.name}`);

  // --- 1. Show loader
  const loader = actionsContainer.querySelector(".loader");
  if (loader) loader.style.display = "inline-block";

  const weekKey = selectedMonday.toISOString().split("T")[0];
  const currentWeekFolder = `week-${selectedMonday.toLocaleDateString("en-US", {
    month: "short",
    day: "numeric"
  }).replace(" ", "-").toLowerCase()}`;

  const passedDays = [];
  const notStartedDays = [];
  const allDayStatuses = []; // Track status of each day for range logic

  // --- 2. Check each day for captions_log.txt
  for (let dayIndex = 1; dayIndex <= 7; dayIndex++) {
    const dayName = dayNames[dayIndex - 1];
    const captionsLogPath = `users/${user.name}/${currentWeekFolder}/${account.name}/${dayName}/captions_log.txt`;

    const dateForDay = new Date(selectedMonday);
    dateForDay.setDate(selectedMonday.getDate() + (dayIndex - 1));

    // ✅ Skip days already yellow, red, or green
// ✅ Only skip yellow days (future)
// ✅ If yellow, mark UI and skip it
const currentStatus = account.weeks[weekKey]?.[dayIndex]?.status;
if (currentStatus === "yellow") {
  const shortDay = dayName.slice(0, 3);
  const tooltip = `${shortDay} ${dateForDay.getDate()}: Day not started`;

  updateDayBoxUI(user.name, account.name, dayIndex, "bg-yellow-400", tooltip);

  console.log(`⏩ Marked ${dayName} (${dateForDay.toISOString().split("T")[0]}) as yellow`);
  allDayStatuses.push({ date: dateForDay, status: currentStatus });
  continue; // do NOT include in captions log or API
}


    try {
      const resp = await fetch(`${captionsLogPath}?t=${Date.now()}`, { method: "HEAD", cache: "no-store" });

      if (!resp.ok) {
        // ❌ File is missing → mark orange
        const shortDay = dayName.slice(0, 3);
        const tooltip = `${shortDay} ${dateForDay.getDate()}: captions_log.txt missing`;

        console.warn(`⚠️ Missing captions_log.txt for ${account.name} → ${dayName}`);
        updateDayBoxUI(user.name, account.name, dayIndex, "bg-orange-400", tooltip);

        if (!account.weeks[weekKey]) account.weeks[weekKey] = {};
        account.weeks[weekKey][dayIndex] = {
          status: "orange",
          date: dateForDay.toISOString().split("T")[0]
        };

        allDayStatuses.push({ date: dateForDay, status: "orange" });
      } else {
        // ✅ File exists → mark as grey
        const shortDay = dayName.slice(0, 3);
        const tooltip = `${shortDay} ${dateForDay.getDate()}: Not analysed`;

        console.log(`✅ captions_log.txt exists for ${account.name} → ${dayName}`);
        updateDayBoxUI(user.name, account.name, dayIndex, "bg-gray-300", tooltip);

        if (!account.weeks[weekKey]) account.weeks[weekKey] = {};
        account.weeks[weekKey][dayIndex] = {
          status: "grey",
          date: dateForDay.toISOString().split("T")[0]
        };

        allDayStatuses.push({ date: dateForDay, status: "grey" });
      }
    } catch (err) {
      console.error(`❌ Error checking captions_log.txt for ${account.name} - ${dayName}`, err);
    }
  }

  // --- 3. Save updated state
  await saveStateToServer();

  // --- 4. Update Yellow/Grey statuses for this user
  await updateYellowDays(user);

  // --- 5. Analyze yellow vs passed days
  const today = new Date();
  for (let i = 1; i <= 7; i++) {
    const dayData = account.weeks[weekKey]?.[i];
    if (!dayData) continue;

    const dayDate = new Date(dayData.date);

    if (dayData.status === "yellow") {
      notStartedDays.push(dayDate.getDate());
    } else {
      passedDays.push(dayDate.getDate());
    }
  }

  // --- 6. Build summary message
  let message = "";
  if (passedDays.length > 0) {
    message += `${passedDays.join(", ")} days are passed and verified\n`;
  }
  if (notStartedDays.length > 0) {
    message += `${notStartedDays.join(", ")} days didn't start yet`;
  }
  if (message.trim() === "") {
    message = "No days found to analyze.";
  }
  console.log("SUMMARY:\n" + message);

  // --- 7. VALID RANGE CALCULATION ---
  const hasOrange = allDayStatuses.some(d => d.status === "orange");
  const allGreyOrYellow = allDayStatuses.every(d => ["grey", "yellow"].includes(d.status));

  let validRangeMessage = "";

  if (hasOrange) {
    validRangeMessage = "Valid range for this refresh: Week is not fully valid with captions txt";
  } else {
    // Find first non-yellow (start) and last non-yellow (end)
    const validDays = allDayStatuses.filter(d => d.status === "grey");

    if (validDays.length === 7) {
      // All days are valid
      const firstDate = allDayStatuses[0].date.toISOString().split("T")[0];
      const lastDate = allDayStatuses[6].date.toISOString().split("T")[0];
      validRangeMessage = `Valid range for this refresh: ${firstDate}:${lastDate}`;
    } else if (validDays.length > 0) {
      // Some days are valid but future days (yellow) exist at the end
      const firstDate = validDays[0].date.toISOString().split("T")[0];
      const lastDate = validDays[validDays.length - 1].date.toISOString().split("T")[0];
      validRangeMessage = `Valid range for this refresh: ${firstDate}:${lastDate}`;
    } else {
      validRangeMessage = "Valid range for this refresh: Week is not fully valid with captions txt";
    }
  }

  console.log(validRangeMessage);
  
// --- 8. Use range to scrape data and update boxes
const folderName = account.name; // The Threads account folder
const country = user.country || "Nigeria"; // fallback to Nigeria if not set

// ✅ Only proceed if the message actually has a proper date range
if (
  validRangeMessage.startsWith("Valid range for this refresh:") &&
  !validRangeMessage.includes("Week is not fully valid with captions txt")
) {
  // Clean prefix
  const cleanMessage = validRangeMessage.replace("Valid range for this refresh: ", "").trim();

  // Split into [start, end]
  const [startDate, endDate] = cleanMessage.split(":");

  console.log("Start Date →", startDate);
  console.log("End Date →", endDate);

  const apiUrl = `https://stephieluv.com/manager/scraped/index.php?folder=${encodeURIComponent(folderName)}&start=${encodeURIComponent(startDate)}&end=${encodeURIComponent(endDate)}&country=${encodeURIComponent(country)}&debug=1`;
  console.log("API URL →", apiUrl);

  try {
const data = await fetchScraper(apiUrl, loader);
if (!data) return; // stop if invalid session
    console.log("SCRAPER RESPONSE:", data);

    if (data.posts && data.posts.length > 0) {
      // Process and update boxes
      await processScraperData(user.name, account.name, weekKey, data);
      // 💾 Save updated state so Wed/Thu results persist in stored.txt
console.log(`💾 Saved updated results for account: ${account.name}`);
    } else {
      console.warn("❌ API returned no posts, skipping processing.");
    }
  } catch (err) {
    console.error("❌ Error fetching scraper API:", err);
  }
} else {
  console.warn("⛔ Skipping API call: Week is not fully valid or no proper range.");
}


// --- 9. Hide loader
if (loader) loader.style.display = "none";

console.log(`✅ Refresh check completed for account: ${account.name}`);

// --- Save the last refresh timestamp in the user's local time ---
const userTimezone = countryTimezones[user.country] || "UTC";
const now = new Date();

const formattedDate = new Intl.DateTimeFormat("en-US", {
  timeZone: userTimezone,
  month: "short",  // Sep
  day: "numeric",  // 7
  hour: "2-digit",
  minute: "2-digit",
  hour12: false
}).format(now); // Example: "Sep 7, 14:35"

// Remove the comma (Sep 7, 14:35 -> Sep 7 14:35)
account.last_update_refresh = formattedDate.replace(",", "");

console.log(`💾 Last update saved for ${account.name} (${user.country} time): ${account.last_update_refresh}`);


// --- 10. Save final state so it's persistent
await saveStateToServer();

// --- 11. Reload state from backend to get fresh results
await loadStateFromServer();

// --- 12. Rebuild info box with the latest data
buildAccountInfoBox(item);
});





  // Insert refresh button right before loader
  actionsContainer.appendChild(refreshBtn);
actionsContainer.appendChild(infoBtn);
// Add to actions container (or document.body if you prefer)
actionsContainer.appendChild(infoBox);
  // --- Loader ---
  const loader = document.createElement("span");
  loader.className = "loader";
  loader.style.display = "none"; // hidden by default
  actionsContainer.appendChild(loader);
}

      const dayBoxes = item.querySelectorAll(".day-box");
      const weekKey = selectedMonday.toISOString().split("T")[0];
      
       // === Account Edit Button ===
 
        // Auto-fill missing days for existing accounts
if (!account.weeks) account.weeks = {};
if (!account.weeks[weekKey]) {
  console.warn(`Week ${weekKey} does not exist for account ${account.name}. Skipping creation.`);
    account.weeks[weekKey] = {};
}

  for (let i = 1; i <= 7; i++) {
    if (!account.weeks[weekKey][i]) {
      const dayDate = new Date(selectedMonday);
      dayDate.setDate(selectedMonday.getDate() + (i - 1));
      const formattedDate = dayDate.toISOString().split("T")[0];

      account.weeks[weekKey][i] = { status: "grey", date: formattedDate };
    }
  }


      dayBoxes.forEach((box) => {
        const dayIndex = parseInt(box.dataset.day);

        // ✅ Use resultsMap instead of stored.txt
// ✅ Use resultsMap instead of stored.txt
// ✅ Use resultsMap instead of stored.txt
const weekResults = resultsMap?.[user.name]?.[account.name]?.[weekKey];

if (weekResults && weekResults[dayIndex]) {
  // --- Case: this day has analysis results
  const resultObj = weekResults[dayIndex];

  if (typeof resultObj === "object") {
    const savedDate = new Date(resultObj.date);
    const shortDay = savedDate.toLocaleDateString("en-US", { weekday: "short" }); // Wed
    const dayNum = savedDate.getDate(); // 17
    box.setAttribute("data-tooltip", `${shortDay} ${dayNum}: ${resultObj.result}`);
  } else {
    box.setAttribute("data-tooltip", resultObj);
  }
} else {
  // --- Case: no results yet -> check status
  const currentDayData = account.weeks?.[weekKey]?.[dayIndex];
  if (currentDayData) {
    const savedDate = new Date(currentDayData.date);
    const shortDay = savedDate.toLocaleDateString("en-US", { weekday: "short" });
    const dayNum = savedDate.getDate();

    if (currentDayData.status === "grey") {
      box.setAttribute("data-tooltip", `${shortDay} ${dayNum}: not analysed`);
    } else if (currentDayData.status === "yellow") {
      box.setAttribute("data-tooltip", `${shortDay} ${dayNum}: Day not started`);
    } else {
      box.removeAttribute("data-tooltip");
    }
  } else {
    box.removeAttribute("data-tooltip");
  }
}




        // Keep green color
if (account.weeks && account.weeks[weekKey] && account.weeks[weekKey][dayIndex]) {
  const status = account.weeks[weekKey][dayIndex].status;

  if (account.weeks && account.weeks[weekKey] && account.weeks[weekKey][dayIndex]) {
    const status = account.weeks[weekKey][dayIndex].status;


const dateObj = new Date(account.weeks[weekKey][dayIndex].date);

const formattedDate = dateObj.toLocaleDateString("en-US", { weekday: "short" }) + " " + dateObj.getDate();




if (status === "green") {
  box.classList.add("bg-green-500");

  // ✅ Try to get actual result from state.results
  const dayResult = resultsMap?.[user.name]?.[account.name]?.[weekKey]?.[dayIndex];

  if (dayResult && dayResult.result) {
    // Example: "5 from 8 were posted"
    box.setAttribute("data-tooltip", `${formattedDate}: ${dayResult.result}`);
  } else {
  // 🟡 Fallback text when there is no result yet
  box.setAttribute("data-tooltip", `${formattedDate}: Not analysed`);
  }
}else if (status === "red") {
  box.classList.add("bg-red-500");
  box.classList.remove("hover:bg-gray-300");

  // 🔹 Check if we have result details for this day
  const dayResult = resultsMap?.[user.name]?.[account.name]?.[weekKey]?.[dayIndex];

  if (dayResult && dayResult.result) {
    // ✅ Show full details like "0 from 8 posted | Not same order | Posted: 25"
    box.setAttribute("data-tooltip", `${formattedDate}: ${dayResult.result}`);
  } else {
    // Fallback if no detailed result is stored
    box.setAttribute("data-tooltip", `${formattedDate}: Missing captions ERROR1`);
  }
} else if (status === "orange") {
  box.classList.add("bg-orange-400");
  box.classList.remove("hover:bg-gray-300");
  box.setAttribute("data-tooltip", `${formattedDate}: captions_log.txt missing`);
} else if (status === "grey") {
  // Grey boxes should keep hover effect
  box.classList.add("bg-gray-300", "hover:bg-gray-300", "transition-none", "pointer-events-auto");
  box.setAttribute("data-tooltip", `${formattedDate}: Not analysed`);
} else if (status === "yellow") {
  // Yellow boxes must NEVER have hover:bg-gray-300
  box.classList.add("bg-yellow-400");
  box.classList.remove("hover:bg-gray-300", "bg-gray-300");
  box.style.backgroundColor = ""; // Ensure no inline override
  box.setAttribute("data-tooltip", `${formattedDate}: Day not started`);
}



  }

}

        // On click
box.addEventListener("click", (e) => {
  e.stopPropagation();

  const clickedDate = new Date(selectedMonday);
  clickedDate.setDate(clickedDate.getDate() + (dayIndex - 1));

  const weekKey = selectedMonday.toISOString().split("T")[0];
  const dayData = account.weeks?.[weekKey]?.[dayIndex];

  // ✅ Check if this day is marked as yellow
  if (dayData?.status === "yellow") {
    const dayName = dayNames[dayIndex - 1];
    alert(`❌ Cannot scrape for ${dayName} (${dayData.date}).\nThe day has NOT started yet in ${user.country}.`);
    console.warn(`Blocked scraping attempt: Day ${dayData.date} is yellow for ${user.country}`);
    return; // Stop further execution
  }

  // ✅ If not yellow, proceed normally
  checkCaptionsForDay(user.name, account.name, dayIndex, clickedDate);
});

      });
      
        // ✅ Build info box for this account
buildAccountInfoBox(item);

      ul.appendChild(item);
    });

    usersContainer.appendChild(node);
  });
    // ✅ Initialize hover for info buttons after DOM is ready
//   initInfoBoxHover();
  initInfoBoxClick();
}

function initInfoBoxClick() {
  let activeInfoBox = null;
  let activeButton = null;

  document.querySelectorAll(".info-btn").forEach(infoBtn => {
    const accountItem = infoBtn.closest(".account-item");
    const infoBox = accountItem?.querySelector(".account-info-box");
    if (!infoBox) return;

    // default hidden (no Tailwind 'hidden' class; use inline styles)
    infoBox.style.display = "none";
    infoBox.style.opacity = "0";
    infoBox.style.transition = "opacity 0.2s ease";

    // keep clicks inside the box from closing it
    infoBox.addEventListener("click", (e) => e.stopPropagation());

infoBtn.addEventListener("click", (e) => {
  e.stopPropagation();

  // toggle off if same button
  if (activeButton === infoBtn) {
    infoBox.style.opacity = "0";
    setTimeout(() => (infoBox.style.display = "none"), 200);
    infoBtn.classList.remove("ring-2", "ring-black", "rounded-none");
    activeButton = null;
    activeInfoBox = null;
    return;
  }

  // close previous box...
  if (activeInfoBox && activeInfoBox !== infoBox) {
    activeInfoBox.style.opacity = "0";
    activeInfoBox.style.display = "none";
    if (activeButton) {
      activeButton.classList.remove("ring-2", "ring-black", "rounded-none");
    }
  }

  // ✅ ADD THIS: rebuild fresh content from stored.txt
  buildAccountInfoBox(accountItem);

  // open this one
  if (!document.body.contains(infoBox)) {
    document.body.appendChild(infoBox);
  }

  infoBox.style.display = "block";
  const btnRect = infoBtn.getBoundingClientRect();
  infoBox.style.top = `${btnRect.top - 195 + window.scrollY}px`;
  infoBox.style.left = `${btnRect.right + 20 + window.scrollX}px`;

  requestAnimationFrame(() => (infoBox.style.opacity = "1"));

  infoBtn.classList.add("ring-2", "ring-grey", "rounded-none", "box-border");

  activeButton = infoBtn;
  activeInfoBox = infoBox;
});

  });

  // add the outside click handler only once across re-renders
  if (!document.__infoBoxClickOutsideBound) {
    document.addEventListener("click", () => {
      const box = document.querySelector(".account-info-box[style*='display: block']");
      const btn = document.querySelector(".info-btn.ring-2");
      if (box) {
        box.style.opacity = "0";
        setTimeout(() => (box.style.display = "none"), 200);
      }
      if (btn) btn.classList.remove("ring-2", "ring-blue-500", "rounded-full");
    });
    document.__infoBoxClickOutsideBound = true;
  }
}

function buildAccountInfoBox(accountElement) {
  const infoBox = accountElement.querySelector(".account-info-box");
  if (!infoBox) return;

  // ✅ Get the account name dynamically
  const accountName = accountElement.querySelector(".accountName")?.textContent || "Account";
  
  // Find this account directly from state to avoid DOM issues
let foundAccount = null;
for (const user of state.users) {
  const acc = user.accounts.find(a => a.name === accountName);
  if (acc) {
    foundAccount = acc;
    break;
  }
}


  // ✅ Add a header at the top of the box
  let infoHtml = `
    <div class="account-info-header" 
         style="font-weight:600; font-size:14px; text-align:center; padding:10px; 
                background:#f3f4f6; border-bottom:1px solid #ddd; border-radius:6px 6px 0 0;">
      ${accountName}
    </div>
    <table class="w-full text-sm border-collapse">
      <thead>
        <tr class="bg-gray-100">
          <th class="p-2 text-center">Day</th>
          <th class="p-2 text-left">Status</th>
          <th class="p-2 text-center">Order</th>
          <th class="p-2 text-center">Posted</th>
        </tr>
      </thead>
      <tbody>
  `;

  // --- Totals for summary row ---
  let totalFirst = 0;      // sum of "8" from "8 from 9 posted"
  let totalSecond = 0;     // sum of "9" from "8 from 9 posted"
  let totalSameOrder = 0;  // count how many days have "Same order"
  let totalPosted = 0;     // sum of all posts like 23 + 24 + 24
  let greenDaysCount = 0;  // count of green day boxes

  for (let dayIndex = 1; dayIndex <= 7; dayIndex++) {
    const dayBox = accountElement.querySelector(`.day-box[data-day="${dayIndex}"]`);
    if (!dayBox) continue;

    const tooltip = dayBox.getAttribute("data-tooltip") || "No data";

    // Detect the color class
    let colorClass = "";
    if (dayBox.classList.contains("bg-green-500")) {
      colorClass = "bg-green-500";
      greenDaysCount++; // count green
    } else if (dayBox.classList.contains("bg-red-500")) colorClass = "bg-red-500";
    else if (dayBox.classList.contains("bg-yellow-400")) colorClass = "bg-yellow-400";
    else if (dayBox.classList.contains("bg-gray-300")) colorClass = "bg-gray-300";
    else if (dayBox.classList.contains("bg-orange-400")) colorClass = "bg-orange-400";

    const tooltipParts = tooltip.split('|');
    const dayLabel = tooltipParts[0].trim().split(':')[0];       // e.g., "Mon 22"
    const statusValue = tooltipParts[0].trim().split(':')[1]?.trim() || ''; // e.g., "8 from 9 posted"
    const orderValue = tooltipParts[1]?.trim() || '';
    const postedValue = tooltipParts[2]?.replace('Posted:', '').trim() || '';

    // --- Extract numbers for totals ---
    // From "8 from 9 posted"
    const match = statusValue.match(/(\d+)\s+from\s+(\d+)/);
    if (match) {
      totalFirst += parseInt(match[1]);  // add first number
      totalSecond += parseInt(match[2]); // add second number
    }

    // Count "Same order"
    if (orderValue === "Same order") {
      totalSameOrder++;
    }

    // Add Posted count
    if (!isNaN(postedValue) && postedValue !== '') {
      totalPosted += parseInt(postedValue);
    }

    // --- Build row for each day ---
    infoHtml += `
      <tr class="border-b">
        <!-- Day text inside the colored box -->
        <td class="p-2 text-center">
          <div class="px-1 py-0.5 text-xs rounded text-white font-semibold ${colorClass}">
            ${dayLabel}
          </div>
        </td>
        
        <!-- Status -->
        <td class="p-2 text-xs" style="font-size:12px !important;">${statusValue}</td>

        <!-- Order -->
        <td class="p-2 text-center text-xs" style="font-size:12px !important;">${orderValue}</td>

        <!-- Posted -->
        <td class="p-2 text-center text-xs" style="font-size:12px !important;">${postedValue}</td>
      </tr>
    `;
  }
// --- After loop: calculate percentages ---
const percentageStatus = totalSecond > 0 ? ((totalFirst / totalSecond) * 100).toFixed(1) : "0.0";
const percentageOrder = ((totalSameOrder / 7) * 100).toFixed(1);
const targetPosts = (foundAccount?.targetPosts || 0) * 7;
const percentagePosts = targetPosts > 0 ? ((totalPosted / targetPosts) * 100).toFixed(1) : "0.0";

// ✅ Decide background for green count
const greenStatusBg = greenDaysCount === 7 ? "bg-green-500" : "bg-red-500";

// --- First row: raw counts ---
// --- First row: raw counts ---
infoHtml += `
  <tr class="border-t-2 border-gray-600 font-bold bg-gray-50">
<!-- First column: green count / 7 -->
<td rowspan="2" class="p-2 text-center align-middle">
  <div class="flex items-center justify-center text-white font-bold ${greenStatusBg}" 
       style="height:35px; width:60px; margin:0 auto; font-size:14px; border-radius:6px;">
    ${greenDaysCount}/7
  </div>
</td>


    <!-- Second column: totals -->
    <td class="p-2 text-center text-xs text-left" style="font-weight: 600;">${totalFirst}/${totalSecond}</td>

    <!-- Third column: same order count -->
    <td class="p-2 text-center text-xs" style="font-weight: 600;">${totalSameOrder}/7</td>

    <!-- Fourth column: total posts vs target -->
    <td class="p-2 text-center text-xs" style="font-weight: 600;">
      ${totalPosted}/${targetPosts}
    </td>
  </tr>
`;

// --- Second row: percentages only ---
infoHtml += `
  <tr class="bg-gray-100">
    <!-- ❌ No first column here because it's merged above -->
    <td class="p-2 text-center text-xs font-bold text-gray-600">${percentageStatus}%</td>
    <td class="p-2 text-center text-xs font-bold text-gray-600">${percentageOrder}%</td>
    <td class="p-2 text-center text-xs font-bold text-gray-600">${percentagePosts}%</td>
  </tr>
`;


// --- Calculate Price dynamically ---
// Step 1: Base value is VA Charge from stored.txt
const vaCharge = foundAccount?.vaCharge || 0;

// Step 2: Subtract (100 - percentagePosts)% of vaCharge
// Example: if percentagePosts = 95.2 → subtract 4.8% of vaCharge
const remainingPostsPercent = 100 - parseFloat(percentagePosts);
const afterFirstCalc = vaCharge - (vaCharge * (remainingPostsPercent / 100));

// Step 3: Subtract (100 - percentageStatus)% of the last result
// Example: if percentageStatus = 97.3 → subtract 2.7% of afterFirstCalc
const remainingStatusPercent = 100 - parseFloat(percentageStatus);
const finalPrice = afterFirstCalc - (afterFirstCalc * (remainingStatusPercent / 100));

// Step 4: Round to 1 decimal
const roundedPrice = finalPrice.toFixed(1);

// --- Price Row ---
infoHtml += `
  <tr class="bg-gray-50 font-bold">
    <td class="p-2 text-center text-xs text-gray-700" style="font-weight:600;">Cost</td>
    <td colspan="3" class="p-2 text-center text-xs text-gray-700" style="font-weight:600;">
      $${roundedPrice}
    </td>
  </tr>
`;

infoHtml += `</tbody></table>`; // <-- close table first


// ✅ Find parent user of this account
let parentUser = null;
for (const u of state.users) {
  if (u.accounts.includes(foundAccount)) {
    parentUser = u;
    break;
  }
}

// ✅ Get the country safely
const userCountry = parentUser?.country || "Unknown";

// ✅ Get last update value or fallback
const lastUpdated = foundAccount?.last_update_refresh || "never used";

// --- Convert lastUpdated (e.g., "Sep 28 22:00") to Date object ---
function parseLastUpdated(dateStr, tz) {
  if (!dateStr || dateStr === "never used") return null;

  const parts = dateStr.trim().split(" ");
  if (parts.length < 3) return null;

  const monthMap = {
    Jan: 0, Feb: 1, Mar: 2, Apr: 3, May: 4, Jun: 5,
    Jul: 6, Aug: 7, Sep: 8, Oct: 9, Nov: 10, Dec: 11
  };

  const monthStr = parts[0];
  const day = parseInt(parts[1]);
  const [hour, minute] = parts[2].split(":").map(Number);
  const month = monthMap[monthStr];
  const nowYear = new Date().getFullYear();

  if (month === undefined || isNaN(day) || isNaN(hour) || isNaN(minute)) return null;

  // ✅ Create a UTC date as if it's in Nigeria timezone
  const dateInNigeria = new Date(Date.UTC(nowYear, month, day, hour, minute));

  // Nigeria offset is UTC+1 → add 1 hour
  const nigeriaOffset = 60 * 60 * 1000;
  return new Date(dateInNigeria.getTime() - nigeriaOffset);
}

function getTimeAgo(lastDate, tz) {
  if (!lastDate) return "never";

  // 🌍 Convert NOW to the same timezone (Nigeria)
  const now = new Date();
  const nowInTZ = new Date(
    new Intl.DateTimeFormat("en-US", {
      timeZone: tz,
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false
    }).format(now)
  );

  const diffMs = nowInTZ - lastDate;

  const diffMinutes = Math.floor(diffMs / (1000 * 60));
  const diffHours = Math.floor(diffMinutes / 60);

  if (diffMinutes < 60) return `${diffMinutes}m ago`;
  if (diffHours < 24) return `${diffHours}h ago`;
  const diffDays = Math.floor(diffHours / 24);
  return `${diffDays}d ago`;
}

// --- Timezone for user
const tz = countryTimezones[userCountry] || "UTC";

// --- Convert lastUpdated to Date and calculate how long ago
const lastUpdatedDate = lastUpdated !== "never used" ? parseLastUpdated(lastUpdated, tz) : null;
const timeAgoText = lastUpdatedDate ? getTimeAgo(lastUpdatedDate) : "never";

// --- Final display ---
infoHtml += `
  <div style="margin-top: 10px; text-align: center; font-size: 12px; color: #555;">
    Last updated: <strong>${lastUpdated}</strong> - ${userCountry} 
    ${timeAgoText !== "never" ? `(${timeAgoText})` : ""}
  </div>
`;


infoBox.innerHTML = infoHtml;
}

function startUserClock(clockElement, selectElement) {
  function updateClock() {
    const tz = countryTimezones[selectElement.value] || "UTC";

    const now = new Date();

    // Format day and month
    const month = now.toLocaleString("en-US", { month: "short", timeZone: tz }); // e.g., Sep
    const day = now.toLocaleString("en-US", { day: "2-digit", timeZone: tz });   // e.g., 22

    // Format hour and minute
    const time = now.toLocaleTimeString("en-US", {
      hour: "2-digit",
      minute: "2-digit",
      hour12: false,
      timeZone: tz
    });

    // Final format: Sep 22 14:37
    clockElement.textContent = `${month} ${day} ${time}`;
  }

  // Run immediately
  updateClock();

  // Update every second
  setInterval(updateClock, 1000);

  // Update instantly when country changes
  selectElement.addEventListener("change", updateClock);
}
async function processScraperData(userName, accountName, weekKey, data) {
  if (!data || !data.posts) {
    console.error("❌ No posts found in API response.");
    return;
  }

  const postsByDay = {};

  // --- Group posts by their date ---
  data.posts.forEach(post => {
    if (!post.date) return;
    if (!postsByDay[post.date]) postsByDay[post.date] = [];
    postsByDay[post.date].push(post);
  });

  console.log("Grouped Posts By Day:", postsByDay);

  const selectedMondayDate = new Date(selectedMonday);

  // --- Loop through all 7 days of the selected week ---
  for (let dayIndex = 1; dayIndex <= 7; dayIndex++) {
    const dateForDay = new Date(selectedMondayDate);
    dateForDay.setDate(selectedMondayDate.getDate() + (dayIndex - 1));

    const formattedDate = dateForDay.toISOString().split("T")[0];

    // ✅ Skip yellow days so they stay yellow
    const currentAccount = state.users
      .find(u => u.name === userName)
      ?.accounts.find(a => a.name === accountName);

    const currentDayStatus = currentAccount?.weeks?.[weekKey]?.[dayIndex]?.status;
    if (currentDayStatus === "yellow") {
      console.log(`⏩ Skipping day ${formattedDate} (yellow) → leave as is`);
      continue;
    }

    const dayPosts = postsByDay[formattedDate] || [];

    // ❌ No posts found for this day → mark red
    if (dayPosts.length === 0) {
      console.warn(`⚠️ No posts found for ${formattedDate}`);
      updateDayBoxUI(userName, accountName, dayIndex, "bg-red-500", `No posts found for ${formattedDate}`);
      continue;
    }

    // --- Read captions_log.txt for this day ---
    const dayName = dayNames[dayIndex - 1];
    const captionsLogPath = `users/${userName}/week-${selectedMonday
      .toLocaleDateString("en-US", { month: "short", day: "numeric" })
      .replace(" ", "-")
      .toLowerCase()}/${accountName}/${dayName}/captions_log.txt`;

    let captionsLog = [];
    try {
      const resp = await fetch(`${captionsLogPath}?t=${Date.now()}`);
      if (resp.ok) {
        const text = await resp.text();
        captionsLog = text.split("\n").map(l => l.trim()).filter(l => l.length > 0);
      } else {
        console.warn(`⚠️ Missing captions_log.txt for ${dayName} (${formattedDate})`);
      }
    } catch (err) {
      console.error(`❌ Failed to fetch captions_log.txt for ${dayName}:`, err);
    }

    // --- Extract scraped captions
    const scrapedCaptions = dayPosts.map(post => post.caption.trim());
    const totalCaptionsFromApi = dayPosts.length;

    // ✅ Finalize like manual click
    await finalizeDayResult(
      userName,
      accountName,
      weekKey,
      dayIndex,
      formattedDate,
      captionsLog,
      scrapedCaptions,
      totalCaptionsFromApi
    );
  }

  // 💾 SAVE FINAL STATE AFTER ALL DAYS ARE PROCESSED
  console.log("💾 Final state before saving:", JSON.stringify(state.results, null, 2));
  await saveStateToServer();
  console.log("✅ Updated results saved to stored.txt");
}


function updateDayBoxUI(userName, accountName, dayIndex, colorClass, tooltipText) {
  document.querySelectorAll(`.day-box[data-day="${dayIndex}"]`).forEach((box) => {
    const accEl = box.closest(".account-item");
    const usrEl = box.closest(".user-card");
    if (!accEl || !usrEl) return;

    // Make sure it's the correct account and user
    if (accEl.querySelector(".accountName")?.textContent !== accountName) return;
    if (usrEl.querySelector(".userName")?.textContent !== userName) return;

    // 🧹 Remove ALL old colors and inline styles
box.classList.remove(
  "bg-green-500",
  "bg-red-500",
  "bg-orange-400",
  "bg-gray-300",
  "bg-yellow-400",
  "hover:bg-gray-300"
);

    box.style.backgroundColor = ""; // remove inline grey/yellow overrides

    // 🆕 Apply the new color
    if (colorClass) {
      box.classList.add(colorClass);
    }

    // ✏️ Update tooltip
// ✏️ Update tooltip (two-attr approach for reliable line breaks)
if (tooltipText) {
  const parts = String(tooltipText).split("\n");
  box.setAttribute("data-tip-line1", parts[0] || "");
  box.setAttribute("data-tip-line2", parts.slice(1).join(" ") || "");
  // keep legacy single-line for old CSS (optional)
  box.setAttribute("data-tooltip", parts.join(" "));
} else {
  box.removeAttribute("data-tip-line1");
  box.removeAttribute("data-tip-line2");
  box.removeAttribute("data-tooltip");
}

  });
}

async function finalizeDayResult(userName, accountName, weekKey, dayIndex, dateString, captionsLog, scrapedCaptions, totalCaptionsFromApi) {
    
      // ✅ Save to state.results
 if (!state.results) state.results = {};
  if (!state.results[userName]) state.results[userName] = {};
  if (!state.results[userName][accountName]) state.results[userName][accountName] = {};
  if (!state.results[userName][accountName][weekKey]) state.results[userName][accountName][weekKey] = {};
  let matchedCount = 0;
  captionsLog.forEach(logCaption => {
    if (scrapedCaptions.includes(logCaption)) matchedCount++;
  });

  // --- Check order consistency (reverse scraped because it's stored backwards) ---
  const reversedScraped = [...scrapedCaptions].reverse();
  let orderStatus = "Same order";
  for (let i = 0; i < Math.min(captionsLog.length, reversedScraped.length); i++) {
    if (captionsLog[i] !== reversedScraped[i]) {
      orderStatus = "Not same order";
      break;
    }
  }

  // ✅ Build final result text
  const resultText = 
    `${matchedCount} from ${captionsLog.length} posted\n` +
    `| ${orderStatus} \n` +
    `| Posted: ${totalCaptionsFromApi}`;

  // Determine color
  let dayStatus;
  if (matchedCount === captionsLog.length) {
    dayStatus = "green";
  } else if (matchedCount < captionsLog.length) {
    dayStatus = "red";
  } else {
    dayStatus = "grey";
  }



  state.results[userName][accountName][weekKey][dayIndex] = {
    date: dateString,
    result: `${matchedCount} from ${captionsLog.length} posted | ${orderStatus} | Posted: ${totalCaptionsFromApi}`
  };

  // ✅ Update local state for this day
  const currentUser = state.users.find(u => u.name === userName);
  const currentAccount = currentUser?.accounts.find(a => a.name === accountName);

  if (currentAccount) {
    if (!currentAccount.weeks[weekKey]) currentAccount.weeks[weekKey] = {};
    currentAccount.weeks[weekKey][dayIndex] = {
      status: dayStatus,
      date: dateString
    };
  }

  // ✅ Update UI
  const shortDayName = new Date(dateString).toLocaleDateString("en-US", { weekday: "short" });
  const dayNum = new Date(dateString).getDate();
  const colorClass = dayStatus === "green" ? "bg-green-500" :
                     dayStatus === "red" ? "bg-red-500" :
                     dayStatus === "orange" ? "bg-orange-400" : null;

  updateDayBoxUI(userName, accountName, dayIndex, colorClass, `${shortDayName} ${dayNum}: ${resultText}`);

  return { matchedCount, resultText, dayStatus };
}


// --- Add New User ---
byId("addUserBtn").addEventListener("click", async () => {
  const input = byId("userName");
  const name = input.value.trim();
  if (!name) return alert("Please enter a user name.");

  // Prevent duplicate usernames
  if (state.users.some((u) => u.name.toLowerCase() === name.toLowerCase())) {
    return alert("User already exists.");
  }

  // Get the currently selected week
  const weekFolderName = "week-" + formatDate(selectedMonday).replace(" ", "-").toLowerCase();

  // --- Step 1: Create user object in state
  const newUser = { id: uid(), name, country: "Nigeria", accounts: [] };
  state.users.push(newUser);

  // --- Step 2: Save state to store.txt
  await saveStateToServer();

  // --- Step 3: Create week folder on the server
  try {
    const resp = await fetch("backend.php?action=createWeekFolder", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        user: newUser.name,
        weekFolder: weekFolderName
      })
    });
    const data = await resp.json();
    console.log(`📂 Week folder created for new user "${newUser.name}":`, data);
  } catch (err) {
    console.error(`❌ Failed to create week folder for user ${newUser.name}`, err);
  }

  // --- Step 4: Clear input and re-render
  input.value = "";
  render(searchBox.value);
});

// --- Search ---
searchBox.addEventListener("input", (e) => render(e.target.value));

// --- Initial Load ---
loadStateFromServer();

// Run immediately once on load
updateYellowDays();

// Then run every 10 minutes
setInterval(updateYellowDays, 10 * 60 * 1000);

// --- Week Selector Logic ---
const weekBtn = document.getElementById("weekSelectorBtn");
const weekPicker = document.getElementById("weekPicker");

function formatDate(date) {
  return date.toLocaleDateString("en-US", { 
    day: "numeric", 
    month: "short", 
    timeZone: "UTC"   // ✅ Force UTC to avoid timezone shifting
  });
}

function getCurrentMonday() {
  const now = new Date();

  // Get current UTC date
  const utcYear = now.getUTCFullYear();
  const utcMonth = now.getUTCMonth();
  const utcDate = now.getUTCDate();

  const todayUTC = new Date(Date.UTC(utcYear, utcMonth, utcDate));

  const day = todayUTC.getUTCDay(); // 0 = Sunday, 1 = Monday
  const mondayOffset = (day + 6) % 7; // Make Monday the start
  todayUTC.setUTCDate(todayUTC.getUTCDate() - mondayOffset);

  return todayUTC;
}

console.log("TEST Monday:", getCurrentMonday().toISOString().split("T")[0]);

selectedMonday = getCurrentMonday(); // no 'let'!
function updateWeekButtonText(date) {
  weekBtn.textContent = `Week ${formatDate(date)}`;
}
updateWeekButtonText(selectedMonday);

weekBtn.addEventListener("click", () => weekPicker.showPicker());

// --- Create week folder for each user ---
async function createWeekFolders(weekKey) {
  const weekFolderName = "week-" + formatDate(selectedMonday).replace(" ", "-").toLowerCase();

  for (const user of state.users) {
    try {
      await fetch("backend.php?action=createWeekFolder", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          user: user.name,
          weekFolder: weekFolderName
        })
      });
      console.log(`📂 Week folder created for user ${user.name}: ${weekFolderName}`);
    } catch (err) {
      console.error("Failed to create week folder for", user.name, err);
    }
  }
}

weekPicker.addEventListener("change", async (e) => {
  // Parse the input YYYY-MM-DD yourself and build a UTC date
  const [y, m, d] = e.target.value.split("-").map(Number);
  const pickedUTC = new Date(Date.UTC(y, m - 1, d)); // midnight UTC

  // Compute Monday in UTC
  const day = pickedUTC.getUTCDay();            // 0=Sun, 1=Mon, ... 6=Sat
  const mondayOffset = (day + 6) % 7;           // days to subtract to reach Monday
  pickedUTC.setUTCDate(pickedUTC.getUTCDate() - mondayOffset);

  // This is your canonical Monday
  selectedMonday = pickedUTC;

  console.log("DEBUG - Picker raw date:", e.target.value);
  console.log("DEBUG - Calculated Monday (UTC):", selectedMonday.toISOString().split("T")[0]);

  console.log(`📆 Switched to week starting ${selectedMonday.toISOString().split("T")[0]}`);
  updateWeekButtonText(selectedMonday);

  // --- STEP 1: Update only yellow/grey statuses (NO folder creation, NO stored.txt ghost weeks)
  const weekKey = selectedMonday.toISOString().split("T")[0];

  state.users.forEach(user => {
    const timezone = countryTimezones[user.country] || "UTC";
    const nowUtc = new Date();

    const nowInCountry = new Date(
      new Intl.DateTimeFormat("en-US", {
        timeZone: timezone,
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false
      }).format(nowUtc)
    );
    

    user.accounts.forEach(account => {
      if (!account.weeks) account.weeks = {};

if (!account.weeks[weekKey]) {
  // ✅ Only create an empty week if it truly doesn't exist
  console.log(`⚠️ Week ${weekKey} not found for account "${account.name}". Creating a NEW week...`);
  account.weeks[weekKey] = {};
} else {
  console.log(`📂 Week ${weekKey} already exists for account "${account.name}". Loading saved data.`);
}


      console.log(`🔄 Updating yellow/grey statuses for week ${weekKey}, account "${account.name}"`);

for (let i = 1; i <= 7; i++) {
  const dayDateUTC = new Date(selectedMonday);      // clone UTC Monday
  dayDateUTC.setUTCDate(dayDateUTC.getUTCDate() + (i - 1)); // add i-1 days in UTC

  const dayStartInCountry = new Date(
    new Intl.DateTimeFormat("en-US", {
      timeZone: timezone,
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false
    }).format(new Date(`${dayDateUTC.toISOString().split("T")[0]}T00:00:00Z`))
  );

  const status = nowInCountry < dayStartInCountry ? "yellow" : "grey";

  if (!account.weeks[weekKey][i]) {
    // ✅ Create day if it doesn't exist
    account.weeks[weekKey][i] = { status, date: dayDateUTC.toISOString().split("T")[0] };
  } else if (account.weeks[weekKey][i].status === "yellow") {
    // ✅ Only update yellow dynamically
    account.weeks[weekKey][i].status = status;
  }
}

    });
  });

  await saveStateToServer();
  console.log("💾 Week data saved to stored.txt (only yellow/grey updated)");

  await updateYellowDays();
  console.log("🔄 Yellow/Grey verification done for new week");

  render(searchBox.value);
});

window.addEventListener("load", () => {
    
      const weekPicker = document.getElementById("weekPicker");

  if (weekPicker) {
    weekPicker.value = ""; // Clear preselected date
    console.log("🗑️ Week picker reset to empty on page load");
  }
  selectedMonday = getCurrentMonday();
  console.log("DEBUG Initial Selected Monday:", selectedMonday.toISOString().split("T")[0]);
  updateWeekButtonText(selectedMonday);
});

async function updateYellowDays(targetUser = null) {
  const nowUTC = new Date();
  let hasChanges = false;

  const usersToCheck = targetUser ? [targetUser] : state.users;

  usersToCheck.forEach(user => {
    const tz = countryTimezones[user.country] || "UTC";

    // Correct “now” in the user’s country (for logging) + local date (for logic)
    const localNowVerbose = formatLocalDateTimeVerbose(nowUTC, tz);
    const localTodayYMD = getLocalYMD(nowUTC, tz);

    console.log(`\n🌍 ${user.name} — ${user.country} (${tz})`);
    console.log(`   Local now: ${localNowVerbose}`);
    console.log(`   Local today (Y-M-D): ${localTodayYMD}`);

    user.accounts.forEach(account => {
      const weekKey = selectedMonday.toISOString().split("T")[0];
      if (!account.weeks || !account.weeks[weekKey]) return;

      for (let i = 1; i <= 7; i++) {
        const dayData = account.weeks[weekKey][i];
        if (!dayData) continue;

        const shortDay = new Date(dayData.date).toLocaleDateString("en-US", { weekday: "short" });
        const relation = dayData.date > localTodayYMD ? "FUTURE → YELLOW" : "TODAY/PAST → GREY";
        console.log(`   ${shortDay} (${dayData.date}) vs ${localTodayYMD}: ${relation}`);

        // ✅ Yellow if the scheduled date is strictly in the future (in that country)
        if (dayData.date > localTodayYMD) {
          if (dayData.status !== "yellow") {
            dayData.status = "yellow";
            hasChanges = true;
          }
        } else {
if (dayData.status === "yellow") {
  if (dayData.date <= localTodayYMD) {
    // ✅ Only update yellow → grey when the day actually starts
    dayData.status = "grey";
    hasChanges = true;
  }
}
        }

        // Visual refresh animation for this box
        const boxSelector = `.account-item .day-box[data-day="${i}"]`;
        document.querySelectorAll(boxSelector).forEach(box => {
          const accEl = box.closest(".account-item");
          if (
            accEl.querySelector(".accountName").textContent === account.name &&
            accEl.closest(".user-card").querySelector(".userName").textContent === user.name
          ) {
            box.classList.add("refresh-animate");
            setTimeout(() => box.classList.remove("refresh-animate"), 800);
          }
        });
      }
    });
  });

  if (hasChanges) {
    await saveStateToServer();
    render(searchBox.value);
    console.log("✅ Yellow/grey statuses updated based on country local date.");
  }
}

function getLocalYMD(dateUTC, tz) {
  const parts = new Intl.DateTimeFormat("en-CA", {
    timeZone: tz,
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  }).formatToParts(dateUTC);
  const val = (t) => parts.find(p => p.type === t).value;
  return `${val("year")}-${val("month")}-${val("day")}`; // e.g. 2025-09-21
}

function formatLocalDateTimeVerbose(dateUTC, tz) {
  return new Intl.DateTimeFormat("en-GB", {
    timeZone: tz,
    dateStyle: "full",
    timeStyle: "long"
  }).format(dateUTC);
}

// --- Check Captions for Day ---
async function checkCaptionsForDay(userName, accountName, dayIndex, clickedDate) {
  // Find the clicked account item
  const accountItem = [...document.querySelectorAll(".account-item")].find(el =>
    el.querySelector(".accountName")?.textContent === accountName &&
    el.closest(".user-card").querySelector(".userName")?.textContent === userName
  );

  // Find the loader inside this account
  const loader = accountItem?.querySelector(".loader");
  if (loader) loader.style.display = "inline-block"; // Show loader at start
    
      let dayStatus = null;  // ✅ Declare here at the start
  const dayName = dayNames[dayIndex - 1];
  const dateString = clickedDate.toISOString().split("T")[0];
  const currentWeekFolder = `week-${selectedMonday.toLocaleDateString("en-US", {
    month: "short",
    day: "numeric"
  }).replace(" ", "-").toLowerCase()}`; // e.g., week-sep-15

  // 1. --- Ensure folder structure exists ---
// 1. --- Ensure folder structure exists ---
const checkFolderUrl = `backend.php?action=checkAndCreateFolders`;
try {
  const resp = await fetch(checkFolderUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      user: userName,
      weekFolder: currentWeekFolder,
      account: accountName,
      day: dayName
    })
  });
  const folderResult = await resp.json();

  if (folderResult.success) {
    console.log(`📂 Folder verified for ${userName}/${currentWeekFolder}/${accountName}`);

    // ✅ Only now update stored.txt because folders truly exist
    const currentUserObj = state.users.find(u => u.name === userName);
    if (currentUserObj) {
      const currentAccountObj = currentUserObj.accounts.find(a => a.name === accountName);
      if (currentAccountObj) {
        const weekKey = selectedMonday.toISOString().split("T")[0];
        if (!currentAccountObj.weeks[weekKey]) {
          currentAccountObj.weeks[weekKey] = {};
        }
      }
    }
    await saveStateToServer();

  } else {
    alert(`❌ Folder check failed: ${folderResult.error}`);
    return; // Stop execution
  }
} catch (err) {
  alert("❌ Failed to verify folder structure.");
  console.error(err);
  return;
}


// 2. --- Check if captions_log.txt exists ---
// 2. --- Check if captions_log.txt exists (silent, no red 404 errors) ---
const captionsLogPath = `users/${userName}/${currentWeekFolder}/${accountName}/${dayName}/captions_log.txt`;

try {
  const logResp = await fetch(`${captionsLogPath}?t=${Date.now()}`, {
    method: "HEAD",
    cache: "no-store"
  });

if (!logResp.ok) {
  console.warn(`⚠️ captions_log.txt does NOT exist at ${captionsLogPath}`);

  // 🔹 Show loader to indicate error
  if (loader) loader.style.display = "inline-block";

  const weekKey = selectedMonday.toISOString().split("T")[0];
  const u = state.users.find(u => u.name === userName);
  if (u) {
    const a = u.accounts.find(a => a.name === accountName);
    if (a) {
      if (!a.weeks) a.weeks = {};
      if (!a.weeks[weekKey]) a.weeks[weekKey] = {};
      a.weeks[weekKey][dayIndex] = {
        status: "orange",
        date: clickedDate.toISOString().split("T")[0]
      };
    }
  }

  await saveStateToServer();

  const shortDay = dayName.slice(0, 3);
  const tip = `${shortDay} ${clickedDate.getDate()}: captions_log.txt missing`;
  updateDayBoxUI(userName, accountName, dayIndex, "bg-orange-400", tip);

  // 🔹 Hide loader after 1.2 sec to indicate error state
  setTimeout(() => {
    if (loader) loader.style.display = "none";
  }, 1200);

  return; // ⛔ Stop here if missing
}


} catch (err) {
  // ✅ Catch prevents red errors if server is unreachable
  console.warn("HEAD request failed silently:", err);
  return;
}



  // 3. --- Now read captions_log.txt content ---
  let captionsLog = [];
  try {
    const logResp = await fetch(`${captionsLogPath}?t=${Date.now()}`, { cache: "no-store" });
    const logText = await logResp.text();
    captionsLog = logText.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
  } catch (err) {
    alert(`❌ Cannot read captions_log.txt for ${dayName}`);
    console.error(err);
    return;
  }

  if (captionsLog.length === 0) {
    alert(`No captions found in captions_log.txt for ${dayName}`);
    if (loader) loader.style.display = "none";
    return;
  }

  console.log("Captions from captions_log.txt:", captionsLog);

  // 4. --- Scraper API call ---
  const country = state.users.find(u => u.name === userName)?.country || "Nigeria";
  const apiUrl = `https://stephieluv.com/manager/scraped/index.php?folder=${encodeURIComponent(
    accountName
  )}&start=${dateString}&end=${dateString}&country=${encodeURIComponent(country)}&debug=1`;

let apiRespJson;
try {
apiRespJson = await fetchScraper(apiUrl, loader);
  if (!apiRespJson) return; // stop if invalid
  if (apiRespJson.error) {
    throw new Error(apiRespJson.error || "Unknown error from scraper API");
  }
} catch (error) {
  alert("❌ Failed to scrape posts. Please try again.");
  console.error("Scraper API call failed:", error);
  return;
}

  console.log("Scraper API finished successfully:", apiRespJson);

// 5. --- Read data.txt from scraper folder ---
const dataPath = `https://stephieluv.com/manager/scraped/${accountName}/data.txt`;
let dataContent = [];

try {
  const dataResp = await fetch(dataPath);
  if (!dataResp.ok) throw new Error("Cannot read data.txt");

  const rawJson = await dataResp.json();

  // ✅ Ensure we're extracting ONLY the posts array
  if (Array.isArray(rawJson.posts)) {
      console.log("RAW JSON FROM data.txt:", rawJson);
    dataContent = rawJson.posts;
  } else {
    console.error("Unexpected data.txt format:", rawJson);
    alert("❌ data.txt does not contain a valid 'posts' array.");
    return;
  }
} catch (err) {
  alert("❌ Failed to read data.txt after scraping.");
  console.error("Error reading data.txt:", err);
  return;
}

// Debugging
console.log("DEBUG dataContent:", dataContent);
console.log("Type:", typeof dataContent, "Is Array:", Array.isArray(dataContent));

// 6. --- Filter posts by clicked date ---
const scrapedCaptions = dataContent
  .filter(post => post.date === dateString)
  .map(post => post.caption.trim());

console.log("Scraped captions for exact date:", scrapedCaptions);

// 7. --- Compare captions ---
let matchedCount = 0;
captionsLog.forEach((logCaption) => {
  if (scrapedCaptions.includes(logCaption)) matchedCount++;
});

// --- Check order consistency ---
// Reverse the scraped captions because they're saved backwards
const reversedScraped = [...scrapedCaptions].reverse();

let orderStatus = "Same order";
for (let i = 0; i < Math.min(captionsLog.length, reversedScraped.length); i++) {
  if (captionsLog[i] !== reversedScraped[i]) {
    orderStatus = "Not same order";
    break;
  }
}

const totalCaptionsFromApi = apiRespJson?.total_captions || 0;

// ✅ Build result text with extra "Posted" info
const resultText = 
  `${matchedCount} from ${captionsLog.length} posted\n` +
  `| ${orderStatus} \n` +
  `| Posted: ${totalCaptionsFromApi} `;

console.log(resultText);

  const weekKey = selectedMonday.toISOString().split("T")[0];

  // --- Save to stored.txt through backend ---
  await fetch("backend.php?action=saveResult", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      user: userName,
      account: accountName,
      week: weekKey,
      day: dayIndex,
      result: resultText,
      date: dateString
    })
  });

const currentUserObj = state.users.find((u) => u.name === userName);
if (currentUserObj) {
  const currentAccountObj = currentUserObj.accounts.find((a) => a.name === accountName);
  if (currentAccountObj) {
    if (!currentAccountObj.weeks) currentAccountObj.weeks = {};
    if (!currentAccountObj.weeks[weekKey]) currentAccountObj.weeks[weekKey] = {};

    // Determine day status
    if (matchedCount === captionsLog.length) {
      dayStatus = "green"; // ✅ All captions matched
    } else if (matchedCount < captionsLog.length) {
      dayStatus = "red";   // ❌ Missing captions
    } else {
      dayStatus = "grey";  // Fallback
    }

    // ✅ Update local state for this day
    currentAccountObj.weeks[weekKey][dayIndex] = {
      status: dayStatus,
      date: dateString
    };
  }
}

// ✅ Update results map
// ✅ Initialize results tree safely
if (!state.results) state.results = {};
if (!state.results[userName]) state.results[userName] = {};
if (!state.results[userName][accountName]) state.results[userName][accountName] = {};
if (!state.results[userName][accountName][weekKey]) state.results[userName][accountName][weekKey] = {};

state.results[userName][accountName][weekKey][dayIndex] = {
  date: dateString,
  result: `${matchedCount} from ${captionsLog.length} posted | ${orderStatus} | Posted: ${totalCaptionsFromApi}`
};


await saveStateToServer();

// Update UI
const shortDayName = dayName.slice(0, 3);
const dayNum = clickedDate.getDate();
const color =
  dayStatus === "green" ? "bg-green-500" :
  dayStatus === "red"   ? "bg-red-500"   :
  dayStatus === "orange"? "bg-orange-400": null;

updateDayBoxUI(
  userName,
  accountName,
  dayIndex,
  color,
  `${shortDayName} ${dayNum}: ${resultText}`
);

// ✅ Immediately rebuild the info box with the latest data
const updatedAccountItem = [...document.querySelectorAll(".account-item")].find(el =>
  el.querySelector(".accountName")?.textContent === accountName &&
  el.closest(".user-card").querySelector(".userName")?.textContent === userName
);

if (updatedAccountItem) {
  buildAccountInfoBox(updatedAccountItem);
}

// ✅ Finally hide the loader
if (loader) loader.style.display = "none";

}

// === MODAL RENAME BUTTON ===
document.getElementById("modalRenameBtn").addEventListener("click", async () => {
  if (!currentAccountForModal || !currentUserForModal) return;

  const oldName = currentAccountForModal.name;
  const newName = prompt("Rename account:", oldName);
  if (!newName || newName.trim() === oldName) return;

  // ✅ Prevent duplicates
  if (currentUserForModal.accounts.some(a => a !== currentAccountForModal && a.name.toLowerCase() === newName.toLowerCase())) {
    alert("Another account already has that name.");
    return;
  }

  try {
    // --- 1. Ask backend to rename the folder on disk ---
    const resp = await fetch("backend.php?action=renameAccountFolder", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        user: currentUserForModal.name,
        oldAccountName: oldName,
        newAccountName: newName.trim()
      })
    });

    const data = await resp.json();
    if (!data.success) {
      alert(`❌ Failed to rename folder: ${data.error}`);
      return;
    }

    console.log(`📂 Folder successfully renamed on disk: ${oldName} → ${newName}`);

    // --- 2. Update stored.txt (state) ---
    currentAccountForModal.name = newName.trim();
    await saveStateToServer();

    console.log(`✏️ Account updated in stored.txt: ${oldName} → ${currentAccountForModal.name}`);
    render(searchBox.value);

    // Close modal after rename
    document.getElementById("settingsModal").classList.add("hidden");

  } catch (err) {
    console.error("❌ Error renaming account:", err);
    alert("Server error while renaming account folder.");
  }
});

// === MODAL DELETE BUTTON ===
document.getElementById("modalDeleteBtn").addEventListener("click", async () => {
  if (!currentAccountForModal || !currentUserForModal) return;

  if (!confirm(`Delete account "${currentAccountForModal.name}"?`)) return;

  // Remove account from the list
  currentUserForModal.accounts = currentUserForModal.accounts.filter(a => a !== currentAccountForModal);
  await saveStateToServer();

  // 🔓 Unlock country select if no accounts remain
  const thisUserRow = [...document.querySelectorAll(".user-card")]
    .find(row => row.querySelector(".userName").textContent === currentUserForModal.name);

  if (thisUserRow) {
    const select = thisUserRow.querySelector("select");
    if (select) {
      select.disabled = currentUserForModal.accounts.length > 0;
      select.title = currentUserForModal.accounts.length > 0
        ? "Cannot change country while there are accounts under this user."
        : "Select a country for this user.";
    }
  }

  render(searchBox.value);

  // Close modal after deletion
  document.getElementById("settingsModal").classList.add("hidden");
});


document.getElementById("closeSettingsModal").addEventListener("click", async () => {
  if (currentAccountForModal) {
    const targetPosts = parseInt(document.getElementById("targetPostsInput").value) || 0;
    const vaCharge = parseFloat(document.getElementById("vaChargeInput").value) || 0;

    // Save values to account
    currentAccountForModal.targetPosts = targetPosts;
    currentAccountForModal.vaCharge = vaCharge;

    await saveStateToServer(); // Persist in stored.txt
    console.log(`💾 Saved Target Posts (${targetPosts}) and VA Charge (${vaCharge}) for ${currentAccountForModal.name}`);
  }

  document.getElementById("settingsModal").classList.add("hidden");
});

// === MODAL INSERT EMPTY CAPTIONS BUTTON ===
document.getElementById("modalInsertCaptionsBtn").addEventListener("click", async () => {
  if (!currentAccountForModal || !currentUserForModal) return;

  const weekKey = selectedMonday.toISOString().split("T")[0];
  const weekFolder = "week-" + formatDate(selectedMonday).replace(" ", "-").toLowerCase();

  try {
    const resp = await fetch("backend.php?action=insertEmptyCaptions", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        user: currentUserForModal.name,
        account: currentAccountForModal.name,
        weekFolder: weekFolder
      })
    });

    const data = await resp.json();
    if (!data.success) {
      alert("❌ Failed to insert captions: " + data.error);
      return;
    }

    alert("✅ Empty captions_log.txt inserted for all days of this week.");
    console.log("Inserted captions:", data);

  } catch (err) {
    console.error("❌ Error inserting empty captions:", err);
    alert("Server error while inserting empty captions.");
  }
});

