let floatingUI = null; // Declare floatingUI globally to avoid "not defined" errors
let recordedActions = [];
let stepCounter = 0;
let startTime = null;
let timerInterval = null;

// Start the timer and persist startTime in storage
function startTimer() {
  if (!startTime) startTime = Date.now();
  chrome.storage.local.set({ startTime, isRecording: true, isPaused: false });
  timerInterval = setInterval(updateHeader, 1000);
}
// Stop the timer and clear startTime from storage
function stopTimer() {
  clearInterval(timerInterval);
  timerInterval = null;
  startTime = null;
  chrome.storage.local.remove(['startTime', 'isRecording', 'isPaused']); // Clear persisted data
}

// Calculate elapsed time in HH:MM:SS
function getElapsedTime() {
  const now = Date.now();
  const diff = now - (startTime || 0);

  const hours = Math.floor(diff / (1000 * 60 * 60));
  const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
  const seconds = Math.floor((diff % (1000 * 60)) / 1000);

  return [hours, minutes, seconds].map((n) => String(n).padStart(2, '0')).join(':');
}

// Restore the timer on page reload or tab switch
function restoreTimer() {
  chrome.storage.local.get(['startTime', 'isRecording', 'isPaused'], (result) => {
    const { startTime: savedStartTime, isRecording, isPaused } = result;

    if (isRecording) {
      startTime = savedStartTime;
      if (!isPaused) {
        timerInterval = setInterval(updateHeader, 1000); // Resume the timer
      }
    }
    updateHeader(); // Update header to reflect the restored state
  });
}

// Avoid redeclaration by checking if the variable exists on the window object
// Listen for messages from the .NET app page
window.addEventListener('message', (event) => {
  if (event.source !== window) return; // Only accept messages from the same window

  if (event.data.action === 'open-blank-tab-and-popup') {
    chrome.runtime.sendMessage({ action: 'open-blank-tab-and-popup' });
    console.log("Opening popup....");
  }
  if (event.data.action === 'send-user-data') {
    const { testCaseId, userId, apiKey } = event.data;
    chrome.runtime.sendMessage({
      action: 'send-user-data',
      testCaseId: testCaseId,
      userId: userId,
      apiKey: apiKey
    });
    console.log("Data Received....", testCaseId, userId, apiKey);
  }
});

function initFloatingUI() {
  if (!floatingUI) {
    floatingUI = document.createElement('div');
    floatingUI.id = 'floatingUI';
    floatingUI.style.cssText = `
      position: fixed;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      width: 350px;
      max-height: 200px;
      overflow-y: auto;
      background-color: rgba(255, 255, 255, 0.95);
      border-radius: 10px;
      border: 1px solid #ddd;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      z-index: 9999;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      font-size: 14px;
      padding: 15px;
    `;

    // Create the header
    const header = document.createElement('div');
    header.id = 'floatingHeader';
    header.style.cssText = `
      font-weight: bold;
      margin-bottom: 10px;
      text-align: center;
      color: #333;
      display: flex;
      justify-content: space-between;
      align-items: center;
    `;

    const headerText = document.createElement('span');
    headerText.id = 'floatingHeaderText';
    headerText.textContent = '🔴 Stopped (00:00:00 elapsed)';
    header.appendChild(headerText);

    const stepCounterText = document.createElement('span');
    stepCounterText.id = 'stepCounter';
    stepCounterText.style.cssText = 'font-weight: normal; font-size: 12px; color: #666;';
    stepCounterText.textContent = `Steps: ${stepCounter}`;
    header.appendChild(stepCounterText);

    const closeButton = document.createElement('button');
    closeButton.textContent = '×';
    closeButton.style.cssText = `
      background: none;
      border: none;
      font-size: 18px;
      cursor: pointer;
      color: #999;
    `;
    closeButton.onclick = () => {
      floatingUI.style.display = 'none';
    };
    header.appendChild(closeButton);

    const actionsList = document.createElement('ul');
    actionsList.id = 'actionsList';
    actionsList.style.cssText = `
      list-style-type: none;
      padding: 0;
      margin: 0;
      overflow-y: auto;
    `;

    floatingUI.appendChild(header);
    floatingUI.appendChild(actionsList);
    document.body.appendChild(floatingUI);

    console.log("Floating UI initialized with dynamic header.");
  }
}


// Update the step counter display
function updateStepCounter() {
  const stepCounterElement = document.getElementById('stepCounter');
  if (stepCounterElement) {
    stepCounterElement.textContent = `Steps: ${stepCounter}`;
  }
}

// Function to return icons based on action type
function getActionIcon(actionType) {
  switch (actionType) {
    case 'click': 
      return '🖱️'; // Mouse icon for clicks
    case 'right-click': 
      return '➡️'; // Arrow for right-click
    case 'change': 
      return '✍️'; // Pencil icon for inputs/changes
    case 'navigate': 
      return '🌐'; // Globe icon for navigation
    case 'drag-and-drop': 
      return '🔀'; // Arrows for drag-and-drop
    case 'key': 
      return '⌨️'; // Keyboard icon for key events
    default: 
      return '⚙️'; // Gear for other actions
  }
}

// Update Floating UI with action icons
function updateFloatingUI(action, actionType = 'default') {
  initFloatingUI(); // Ensure the Floating UI is initialized
  const actionsList = document.getElementById('actionsList');

  // Create the list item
  const listItem = document.createElement('li');
  listItem.style.cssText = `
    margin-bottom: 8px;
    padding: 5px;
    border-bottom: 1px solid #eee;
    display: flex;
    align-items: center;
  `;

  // Create an icon span
  const iconSpan = document.createElement('span');
  iconSpan.textContent = getActionIcon(actionType);
  iconSpan.style.cssText = `
    margin-right: 10px;
    font-size: 16px;
  `;

  // Create the text span
  const textSpan = document.createElement('span');
  textSpan.textContent = `[${new Date().toLocaleTimeString()}] ${action}`;

  // Append the icon and text to the list item
  listItem.appendChild(iconSpan);
  listItem.appendChild(textSpan);
  actionsList.appendChild(listItem);

  // Increment the step counter and update the UI
  stepCounter++;
  updateStepCounter();

  // Persist action in storage
  recordedActions.push({ action, actionType }); // Ensure we store as objects for restoring
  chrome.storage.local.set({ recordedActions });

  // Scroll to the bottom of the actions list
  setTimeout(() => {
    actionsList.scrollTop = actionsList.scrollHeight; // Ensure the newly added action is visible
  }, 100); // Delay to account for DOM updates
}

// Restore Floating UI and actions on reload
function restoreFloatingUI() {
  initFloatingUI();

  // Retrieve recorded actions and rebuild the UI
  chrome.storage.local.get(['recordedActions', 'isRecording'], ({ recordedActions: actions = [], isRecording }) => {
    recordedActions = actions;
    stepCounter = actions.length; // Restore step counter from recorded actions
    updateStepCounter(); // Update the step counter in the UI

    const actionsList = document.getElementById('actionsList');
    actionsList.innerHTML = ''; // Clear existing list

    // Rebuild the actions list
    recordedActions.forEach(({ action, actionType = 'default' }) => {
      const listItem = document.createElement('li');
      listItem.style.cssText = `
        margin-bottom: 8px;
        padding: 5px;
        border-bottom: 1px solid #eee;
        display: flex;
        align-items: center;
      `;

      // Create an icon span
      const iconSpan = document.createElement('span');
      iconSpan.textContent = getActionIcon(actionType);
      iconSpan.style.cssText = `
        margin-right: 10px;
        font-size: 16px;
      `;

      // Create the text span
      const textSpan = document.createElement('span');
      textSpan.textContent = action;

      // Append the icon and text to the list item
      listItem.appendChild(iconSpan);
      listItem.appendChild(textSpan);
      actionsList.appendChild(listItem);
    });

    // Auto-scroll to the bottom of the list
    actionsList.scrollTop = actionsList.scrollHeight;

    // Show the Floating UI if recording is active
    if (isRecording) {
      floatingUI.style.display = 'block';
    }
  });

  // Restore the timer if it was running
  restoreTimer();
}

// Handle recording state changes
function handleRecordingStateChange(isRecording, isPaused = false) {
  window.isRecording = isRecording;
  window.isPaused = isPaused;

  if (isRecording) {
    console.log("Recording started. Displaying Floating UI...");
    if (!startTime) startTimer(); // Start the timer if not already running
    initFloatingUI();
    floatingUI.style.display = 'block';
  } else {
    console.log("Recording stopped. Hiding Floating UI and resetting actions...");
    stopTimer(); // Stop the timer
    if (floatingUI) floatingUI.style.display = 'none';

    // Clear recorded actions and reset step counter
    recordedActions = [];
    stepCounter = 0; // Reset the step counter
    updateStepCounter(); // Update the step counter in the UI

    chrome.storage.local.set({ recordedActions: [] }); // Reset persisted actions
    const actionsList = document.getElementById('actionsList');
    if (actionsList) actionsList.innerHTML = ''; // Clear the actions list in the UI
  }

  // Always update the header to reflect the current state
  updateHeader();
}

// Update the header based on recording state (stopped, paused, recording)
function updateHeader() {
  const headerText = document.getElementById('floatingHeaderText');
  const stepCounterElement = document.getElementById('stepCounter');

  const elapsedTime = window.isRecording && !window.isPaused ? getElapsedTime() : '00:00:00';
  const recordingStatus = window.isRecording
    ? (window.isPaused ? '🟡 Paused' : '🟢 Recording Actions')
    : '🔴 Stopped';

  headerText.textContent = `${recordingStatus} (${elapsedTime} elapsed)`;
  stepCounterElement.textContent = `Steps: ${stepCounter}`;
}

// Observe changes in recording state using chrome.storage.onChanged
chrome.storage.onChanged.addListener((changes) => {
  if (changes.isRecording) {
    const isRecording = changes.isRecording.newValue;
    handleRecordingStateChange(isRecording);
  }

  if (changes.recordedActions) {
    recordedActions = changes.recordedActions.newValue || [];
    restoreFloatingUI();
  }
});

// Restore Floating UI and state on page load
document.addEventListener('DOMContentLoaded', () => {
  chrome.storage.local.get(['isRecording', 'isPaused', 'recordedActions'], (result) => {
    const { isRecording, isPaused, recordedActions: actions = [] } = result;

    window.isRecording = isRecording || false;
    window.isPaused = isPaused || false;
    recordedActions = actions;
    stepCounter = actions.length; // Restore step counter from recorded actions
    updateStepCounter();
    handleRecordingStateChange(isRecording, isPaused);
    restoreTimer(); // Restore the timer
  });
});

// Track and persist new actions
function recordAction(action) {
  updateFloatingUI(action); // Update the UI
  chrome.storage.local.set({ recordedActions }); // Save actions
}

// Handle recording state on page load
chrome.storage.local.get(['isRecording', 'isPaused', 'recordedActions'], ({ isRecording, recordedActions: actions = [] }) => {
  window.isRecording = isRecording || false;
  window.isPaused = false;
  recordedActions = actions;
  stepCounter = actions.length; // Restore step counter on page load
  updateStepCounter();
  handleRecordingStateChange(isRecording);
});

// Initialize Floating UI on script load
initFloatingUI();

if (!window.hasOwnProperty('isRecording')) {
  window.isRecording = false;  // Store the recording state on the window object
}

// Add a new variable to track the pause state
if (!window.hasOwnProperty('isPaused')) {
  window.isPaused = false;  // Store the pause state on the window object
}

// Store the source element for drag-and-drop
if (!window.hasOwnProperty('dragSource')) {
  window.dragSource = null;  // Will hold the source element during dragstart
}

// Store the last navigated URL to avoid duplicate navigation events
if (!window.hasOwnProperty('lastNavigatedURL')) {
  window.lastNavigatedURL = null;
}

// Function to generate a relative XPath for an element
function getRelativeXPath(element) {
  if (element.id !== '') {
    return `//*[@id="${element.id}"]`;
  }

  let path = '';
  let currentElement = element;
  while (currentElement && currentElement !== document.body) {
    let tagName = currentElement.tagName.toLowerCase();

    if (currentElement.id !== '') {
      return `//*[@id="${currentElement.id}"]` + path;
    }

    let siblingIndex = 1;
    let siblings = Array.from(currentElement.parentNode.children);
    for (let sibling of siblings) {
      if (sibling === currentElement) {
        break;
      }
      if (sibling.tagName.toLowerCase() === tagName) {
        siblingIndex++;
      }
    }
    path = `/${tagName}[${siblingIndex}]` + path;
    currentElement = currentElement.parentNode;
  }

  return `/html/body${path}`;
}

// Function to safely send messages to the background script and handle errors
function safeSendMessage(data) {
  try {
    chrome.runtime.sendMessage(data, (response) => {
      if (chrome.runtime.lastError) {
        console.warn("Error sending message:", chrome.runtime.lastError.message);
      }
    });
  } catch (err) {
    console.error("Error in safeSendMessage:", err);
  }
}

// Function to track clicks
if (!window.hasOwnProperty('trackClicks')) {
  window.trackClicks = function (event) {
    if (window.isRecording && !window.isPaused) {
      let stepData = {
        eventType: 'click',
        element: event.target.tagName,
        xpath: getRelativeXPath(event.target),
        offsetX: event.offsetX,
        offsetY: event.offsetY,
        button: event.button,
        value: event.target.value || event.target.innerText || '',
        time: new Date().toLocaleString()
      };
      updateFloatingUI(`Click on ${event.target.tagName}`, 'click');
      safeSendMessage({ type: 'record-step', data: stepData });
    }
  };
}

// Function to track right-click (contextmenu)
if (!window.hasOwnProperty('trackRightClick')) {
  window.trackRightClick = function (event) {
    if (window.isRecording && !window.isPaused) {
      // Check if the right-clicked element is a link
      const isLink = event.target.tagName.toLowerCase() === 'a';
      if (isLink) {
        let stepData = {
          eventType: 'right-click',
          action: 'open-in-new-tab', // New property to indicate that the link was opened in a new tab
          url: event.target.href, // The URL of the clicked link
          element: event.target.tagName,
          xpath: getRelativeXPath(event.target),
          offsetX: event.offsetX,
          offsetY: event.offsetY,
          time: new Date().toLocaleString()
        };
        updateFloatingUI(`Right-clicked ${event.target.tagName}`, 'right-click');
        safeSendMessage({ type: 'record-step', data: stepData });
      }
    }
  };
}

// Function to track form inputs (records the whole string when input loses focus)
if (!window.hasOwnProperty('trackInputs')) {
  window.trackInputs = function (event) {
    const tagName = event.target.tagName.toLowerCase();
    if (window.isRecording && !window.isPaused && (tagName === 'input' || tagName === 'textarea' || tagName === 'select')) {
      let stepData = {
        eventType: 'change',
        element: event.target.tagName,
        value: event.target.value,
        xpath: getRelativeXPath(event.target),
        time: new Date().toLocaleString()
      };
      updateFloatingUI(`Changed input value`, 'change');
      safeSendMessage({ type: 'record-step', data: stepData });
    }
  };
}

// Function to track key events (keyup/keydown for non-input fields)
if (!window.hasOwnProperty('trackKeys')) {
  window.trackKeys = function (event) {
    const isInputOrTextarea = event.target.tagName.toLowerCase() === 'input' || event.target.tagName.toLowerCase() === 'textarea';
    if (window.isRecording && !window.isPaused && !isInputOrTextarea) {
      let stepData = {
        eventType: event.type,
        key: event.key,
        xpath: getRelativeXPath(event.target),
        time: new Date().toLocaleString()
      };
      updateFloatingUI(`Pressed key: ${event.key}`, 'key');
      safeSendMessage({ type: 'record-step', data: stepData });
    }
  };
}

// Function to track drag and drop events
if (!window.hasOwnProperty('trackDrag')) {
  window.trackDrag = function (event) {
    if (window.isRecording && !window.isPaused) {
      if (event.type === 'dragstart') {
        window.dragSource = {
          xpath: getRelativeXPath(event.target),
          clientX: event.clientX,
          clientY: event.clientY
        };
      } else if (event.type === 'drop') {
        let stepData = {
          eventType: 'drag-and-drop',
          source: {
            xpath: window.dragSource ? window.dragSource.xpath : null,
            clientX: window.dragSource ? window.dragSource.clientX : null,
            clientY: window.dragSource ? window.dragSource.clientY : null
          },
          destination: {
            xpath: getRelativeXPath(event.target),
            clientX: event.clientX,
            clientY: event.clientY
          },
          time: new Date().toLocaleString()
        };
        updateFloatingUI(`Dragged element`, 'drag-and-drop');
        safeSendMessage({ type: 'record-step', data: stepData });
        window.dragSource = null;
      }
    }
  };
}

// Function to track navigation events (including History API changes)
if (!window.hasOwnProperty('trackNavigation')) {
  window.trackNavigation = function () {
    const currentURL = window.location.href;
    if (window.isRecording && !window.isPaused && currentURL !== window.lastNavigatedURL) {
      let stepData = {
        eventType: 'navigate',
        url: currentURL,
        title: document.title,
        time: new Date().toLocaleString()
      };
      updateFloatingUI(`Navigated to ${currentURL}`, 'navigate');
      safeSendMessage({ type: 'record-step', data: stepData });
      window.lastNavigatedURL = currentURL;
    }
  };
}

// Function to patch history API (pushState and replaceState)
if (!window.hasOwnProperty('patchHistoryAPI')) {
  window.patchHistoryAPI = function () {
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;

    history.pushState = function () {
      originalPushState.apply(this, arguments);
      window.trackNavigation(); // Trigger trackNavigation after pushState is called
    };

    history.replaceState = function () {
      originalReplaceState.apply(this, arguments);
      window.trackNavigation(); // Trigger trackNavigation after replaceState is called
    };

    window.addEventListener('popstate', function () {
      window.trackNavigation(); // Trigger trackNavigation after back/forward navigation
    });
  };
}

// Function to track URL changes more robustly, including when the tab goes inactive or active
function trackTabVisibility() {
  const currentURL = window.location.href;

  if (window.isRecording && !window.isPaused && currentURL !== window.lastNavigatedURL) {
    let stepData = {
      eventType: 'navigate',
      url: currentURL,
      title: document.title,
      time: new Date().toLocaleString()
    };
    safeSendMessage({ type: 'record-step', data: stepData });
    window.lastNavigatedURL = currentURL;
  }
}

// Listen for visibility changes (tab switches, minimize, etc.)
document.addEventListener('visibilitychange', function () {
  if (document.visibilityState === 'visible') {
    // When the tab is refocused or becomes visible again, track navigation
    trackTabVisibility();
  }
});

// Enhanced focus tracking
window.addEventListener('focus', function () {
  trackTabVisibility(); // Track when the user refocuses the tab or window
});

// Add listeners for navigation events and patch History API if not added already
if (!window.hasOwnProperty('listenersAdded')) {
  document.addEventListener('click', window.trackClicks);
  document.addEventListener('contextmenu', window.trackRightClick);
  document.addEventListener('blur', window.trackInputs, true);
  document.addEventListener('keydown', window.trackKeys);
  document.addEventListener('keyup', window.trackKeys);
  document.addEventListener('dragstart', window.trackDrag);
  document.addEventListener('drop', window.trackDrag);
  window.addEventListener('load', window.trackNavigation); // Track on page load
  window.addEventListener('beforeunload', window.trackNavigation); // Track before leaving the page

  // Patch History API to track URL changes via pushState/replaceState
  window.patchHistoryAPI();

  window.listenersAdded = true; // Ensure listeners are only added once
}

// Check the recording state from storage and reapply if needed
chrome.storage.local.get(['isRecording', 'isPaused'], function (result) {
  if (result.isRecording) {
    window.isRecording = true;
  }
  if (result.isPaused) {
    window.isPaused = true;
  }
});

// Handle messages from popup.js or background.js for starting/stopping/pausing the recording
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'start-recording') {
    console.log("Start recording received. Displaying Floating UI...");
    window.isRecording = true;
    window.isPaused = false;
    chrome.storage.local.set({ isRecording: true, isPaused: false });
    window.trackNavigation(); 
    sendResponse({ status: 'ok' });
  } else if (message.action === 'stop-recording') {
    console.log("Stop recording received. Hiding Floating UI...");
    window.isRecording = false;
    chrome.storage.local.set({ isRecording: false });
    sendResponse({ status: 'ok' });
  } else if (message.action === 'pause-recording') {
    console.log("Pause recording received.");
    window.isPaused = true;
    chrome.storage.local.set({ isPaused: true });
    sendResponse({ status: 'ok' });
  } else if (message.action === 'resume-recording') {
    console.log("Resume recording received.");
    window.isPaused = false;
    chrome.storage.local.set({ isPaused: false });
    sendResponse({ status: 'ok' });
  }
});
This is my content.js file in this code the steps are not getting saved properly please fix it.