(function () {
  console.log('Speech to Text Converter: content.js loaded');

  // Inject the microphone button and transcription display if they don't already exist
  if (!document.getElementById('speech-to-text-button')) {
    const button = document.createElement('button');
    button.id = 'speech-to-text-button';
    button.innerHTML = '🎤';
    Object.assign(button.style, {
      position: 'fixed',
      bottom: '20px',
      right: '20px',
      width: '60px',
      height: '60px',
      borderRadius: '50%',
      border: 'none',
      backgroundColor: '#007bff',
      color: '#fff',
      fontSize: '24px',
      cursor: 'pointer',
      zIndex: '10000',
      boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      transition: 'background-color 0.3s',
    });
    button.setAttribute('aria-label', 'Start Speech to Text');
    document.body.appendChild(button);

    // Button hover effect
    button.addEventListener('mouseover', () => {
      button.style.backgroundColor = '#0056b3';
    });

    button.addEventListener('mouseout', () => {
      button.style.backgroundColor = '#007bff';
    });

    // Create transcription display
    if (!document.getElementById('speech-to-text-display')) {
      const transcriptionDisplay = document.createElement('div');
      transcriptionDisplay.id = 'speech-to-text-display';
      Object.assign(transcriptionDisplay.style, {
        position: 'fixed',
        bottom: '90px',
        right: '20px',
        backgroundColor: '#fff',
        padding: '10px 15px',
        borderRadius: '8px',
        boxShadow: '0 2px 6px rgba(0,0,0,0.2)',
        maxWidth: '300px',
        fontSize: '14px',
        zIndex: '10000',
        display: 'none',
        wordWrap: 'break-word',
      });
      transcriptionDisplay.innerText = '';
      document.body.appendChild(transcriptionDisplay);
    }
  }

  const button = document.getElementById('speech-to-text-button');
  const transcriptionDisplay = document.getElementById('speech-to-text-display');
  let isRecording = false;
  let mediaRecorder;
  let audioChunks = [];
  let lastFocusedElement = null;

  // Track the last focused element in the current tab
  document.addEventListener('focusin', (event) => {
    const target = event.target;
    if (
      target.tagName === 'INPUT' ||
      target.tagName === 'TEXTAREA' ||
      target.isContentEditable
    ) {
      lastFocusedElement = target;
      console.log('Updated lastFocusedElement:', lastFocusedElement);
    }
  });

  /**
   * Retrieves all visible and enabled input elements on the page.
   * @returns {HTMLElement[]} Array of input elements.
   */
  function getAllInputElements() {
    const inputs = Array.from(
      document.querySelectorAll('input, textarea, [contenteditable="true"]')
    );
    return inputs.filter((el) => {
      // Ensure the element is visible and not disabled
      const style = window.getComputedStyle(el);
      return (
        style.display !== 'none' &&
        style.visibility !== 'hidden' &&
        !el.hasAttribute('disabled')
      );
    });
  }

  /**
   * Creates and displays a selection modal for choosing the target input field.
   * @param {HTMLElement[]} inputs - Array of input elements.
   */
  function createSelectionModal(inputs) {
    // Create overlay
    const overlay = document.createElement('div');
    overlay.id = 'speech-to-text-overlay';
    Object.assign(overlay.style, {
      position: 'fixed',
      top: '0',
      left: '0',
      width: '100%',
      height: '100%',
      backgroundColor: 'rgba(0,0,0,0.5)',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      zIndex: '10001', // Ensure it's above other elements
    });

    // Create modal container
    const modal = document.createElement('div');
    modal.id = 'speech-to-text-modal';
    Object.assign(modal.style, {
      backgroundColor: '#fff',
      padding: '20px',
      borderRadius: '8px',
      maxHeight: '80%',
      overflowY: 'auto',
      width: '350px',
      boxSizing: 'border-box',
      boxShadow: '0 4px 8px rgba(0,0,0,0.2)',
    });

    // Modal title
    const title = document.createElement('h3');
    title.innerText = 'Select Input Field';
    Object.assign(title.style, {
      marginTop: '0',
      marginBottom: '15px',
      fontSize: '20px',
      textAlign: 'center',
      color: '#333',
    });
    modal.appendChild(title);

    // Instructions
    const instruction = document.createElement('p');
    instruction.innerText = 'Choose the input field where you want to insert the transcription:';
    Object.assign(instruction.style, {
      marginBottom: '15px',
      fontSize: '14px',
      color: '#555',
    });
    modal.appendChild(instruction);

    // List of input fields
    inputs.forEach((el, index) => {
      const label =
        el.getAttribute('aria-label') ||
        el.getAttribute('placeholder') ||
        el.getAttribute('name') ||
        `Input ${index + 1}`;
      const identifier = el.id
        ? `ID: ${el.id}`
        : el.className
        ? `Class: ${el.className}`
        : '';
      const button = document.createElement('button');
      button.innerText = label + (identifier ? ` (${identifier})` : '');
      Object.assign(button.style, {
        display: 'block',
        width: '100%',
        padding: '10px 15px',
        marginBottom: '10px',
        textAlign: 'left',
        border: '1px solid #ccc',
        borderRadius: '4px',
        backgroundColor: '#f9f9f9',
        cursor: 'pointer',
        transition: 'background-color 0.2s',
      });

      // Hover effects
      button.addEventListener('mouseover', () => {
        button.style.backgroundColor = '#e6e6e6';
      });

      button.addEventListener('mouseout', () => {
        button.style.backgroundColor = '#f9f9f9';
      });

      // Click event to select the input field
      button.addEventListener('click', () => {
        lastFocusedElement = inputs[index];
        closeSelectionModal();
        startTranscription();
      });

      modal.appendChild(button);
    });

    // Cancel button
    const cancelButton = document.createElement('button');
    cancelButton.innerText = 'Cancel';
    Object.assign(cancelButton.style, {
      display: 'block',
      width: '100%',
      padding: '10px 15px',
      marginTop: '10px',
      border: 'none',
      borderRadius: '4px',
      backgroundColor: '#d9534f',
      color: '#fff',
      cursor: 'pointer',
      transition: 'background-color 0.2s',
    });

    // Hover effects for cancel button
    cancelButton.addEventListener('mouseover', () => {
      cancelButton.style.backgroundColor = '#c9302c';
    });

    cancelButton.addEventListener('mouseout', () => {
      cancelButton.style.backgroundColor = '#d9534f';
    });

    // Click event to cancel selection
    cancelButton.addEventListener('click', () => {
      closeSelectionModal();
      toggleRecording(false); // Stop recording if canceled
    });

    modal.appendChild(cancelButton);
    overlay.appendChild(modal);
    document.body.appendChild(overlay);
  }

  /**
   * Closes and removes the selection modal from the DOM.
   */
  function closeSelectionModal() {
    const overlay = document.getElementById('speech-to-text-overlay');
    if (overlay) {
      overlay.remove();
    }
  }

  /**
   * Toggles the recording state.
   * @param {boolean} state - Desired recording state.
   * @param {string} [language='en'] - Language code for transcription.
   */
  function toggleRecording(state, language = 'en') {
    isRecording = state;
    if (isRecording) {
      button.classList.add('active');
      transcriptionDisplay.style.display = 'block';
      transcriptionDisplay.innerText = '🎤 Listening...';

      const inputs = getAllInputElements();

      if (inputs.length === 0) {
        alert('No input field found to insert transcription.');
        console.warn('No input field found to insert transcription.');
        toggleRecording(false, language);
        return;
      } else if (inputs.length === 1) {
        lastFocusedElement = inputs[0];
        startTranscription(language);
        lastFocusedElement.focus();
        console.log('Focused on single input:', lastFocusedElement);
      } else {
        // Multiple inputs found, prompt user to select
        createSelectionModal(inputs);
        // Recording will start after selection
      }
    } else {
      button.classList.remove('active');
      stopRecording();
      console.log('Recording stopped');
      transcriptionDisplay.innerText = '🕒 Processing...';
    }
  }

  /**
   * Initiates the recording process after selecting an input field.
   * @param {string} [language='en'] - Language code for transcription.
   */
  function startTranscription(language = 'en') {
    startRecording(language);
    if (lastFocusedElement) {
      lastFocusedElement.focus();
      console.log('Focused on selected input:', lastFocusedElement);
    }
  }

  /**
   * Starts recording audio from the user's microphone.
   * @param {string} [language='en'] - Language code for transcription.
   */
  async function startRecording(language = 'en') {
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      alert('Your browser does not support audio recording.');
      console.error('getUserMedia not supported');
      toggleRecording(false, language);
      return;
    }

    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      mediaRecorder = new MediaRecorder(stream);

      mediaRecorder.start();
      console.log('MediaRecorder started');

      mediaRecorder.ondataavailable = (event) => {
        audioChunks.push(event.data);
        console.log('Audio data available:', event.data);
      };

      mediaRecorder.onstop = async () => {
        const audioBlob = new Blob(audioChunks, { type: 'audio/m4a' });
        console.log('MediaRecorder stopped, Blob created:', audioBlob);

        const base64Audio = await blobToBase64(audioBlob);
        console.log('Audio converted to Base64:', base64Audio.substring(0, 30) + '...');

        sendAudioForTranscription(base64Audio, language);

        // Stop all audio tracks to release the microphone
        stream.getTracks().forEach((track) => track.stop());

        audioChunks = []; // Clear after processing

        isRecording = false;
        button.classList.remove('active');
      };

      mediaRecorder.onerror = (event) => {
        console.error('MediaRecorder Error:', event.error);
        toggleRecording(false);
        transcriptionDisplay.innerText = '❌ Recording error. Please try again.';
      };
    } catch (err) {
      console.error('Error accessing microphone:', err);
      alert('Error accessing microphone. Please check permissions.');
      toggleRecording(false);
      transcriptionDisplay.innerText = '❌ Microphone access denied.';
    }
  }

  /**
   * Stops the ongoing recording.
   */
  function stopRecording() {
    if (mediaRecorder && mediaRecorder.state !== 'inactive') {
      mediaRecorder.stop();
      console.log('MediaRecorder stopping...');
    }
  }

  /**
   * Converts a Blob object to a Base64 string.
   * @param {Blob} blob - The audio Blob.
   * @returns {Promise<string>} Base64 encoded string.
   */
  function blobToBase64(blob) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = function () {
        const dataUrl = reader.result;
        const base64Data = dataUrl.split(',')[1];
        resolve(base64Data);
      };
      reader.onerror = function (error) {
        console.error('FileReader Error:', error);
        reject(error);
      };
      reader.readAsDataURL(blob);
    });
  }

  /**
   * Sends the audio data to the background script for transcription.
   * @param {string} base64Audio - Base64 encoded audio string.
   * @param {string} [language='en'] - Language code for transcription.
   */
  function sendAudioForTranscription(base64Audio, language = 'en') {
    chrome.runtime.sendMessage(
      { type: 'transcribe', audio: { base64: base64Audio }, language },
      () => {
        if (chrome.runtime.lastError) {
          console.error('Runtime error:', chrome.runtime.lastError.message);
          transcriptionDisplay.innerText = '❌ Transcription request failed.';
        } else {
          console.log('Transcription request acknowledged.');
        }
      }
    );
  }

  /**
   * Listens for changes in Chrome storage to receive transcription results.
   */
  chrome.storage.onChanged.addListener((changes, area) => {
    if (
      area === 'local' &&
      changes.latestTranscription &&
      changes.latestTranscription.newValue
    ) {
      const transcription = changes.latestTranscription.newValue;
      console.log('New transcription received via storage:', transcription);

      transcriptionDisplay.innerText = `📝 ${transcription}`;

      // Insert the transcription into the last focused element
      if (lastFocusedElement) {
        insertTextIntoActiveElement(transcription);
      } else {
        console.warn('No last focused element found.');
      }

      // Optional: Hide the transcription display after insertion
      setTimeout(() => {
        transcriptionDisplay.style.display = 'none';
        transcriptionDisplay.innerText = '';
        toggleRecording(false);
      }, 3000);
    }
  });

  /**
   * Inserts text into the active/focused input element.
   * @param {string} text - The transcription text to insert.
   */
  function insertTextIntoActiveElement(text) {
    if (!lastFocusedElement) {
      console.warn('No last focused element to insert text into.');
      return;
    }

    if (
      lastFocusedElement.tagName === 'INPUT' ||
      lastFocusedElement.tagName === 'TEXTAREA'
    ) {
      const startPos = lastFocusedElement.selectionStart;
      const endPos = lastFocusedElement.selectionEnd;
      const beforeValue = lastFocusedElement.value.substring(0, startPos);
      const afterValue = lastFocusedElement.value.substring(
        endPos,
        lastFocusedElement.value.length
      );
      lastFocusedElement.value = beforeValue + text + afterValue;
      lastFocusedElement.selectionStart = lastFocusedElement.selectionEnd =
        startPos + text.length;
      lastFocusedElement.focus();
    } else if (lastFocusedElement.isContentEditable) {
      const selection = window.getSelection();
      if (!selection.rangeCount) return;
      const range = selection.getRangeAt(0);
      range.deleteContents();
      const textNode = document.createTextNode(text);
      range.insertNode(textNode);
      range.setStartAfter(textNode);
      range.setEndAfter(textNode);
      selection.removeAllRanges();
      selection.addRange(range);
    } else {
      console.warn(
        'Last focused element is not an input, textarea, or contenteditable.'
      );
    }
  }

  /**
   * Handles the microphone button click to toggle recording.
   */
  button.addEventListener('click', () => {
    const selectedLanguage = 'en'; // Default language; can be enhanced to allow selection
    toggleRecording(!isRecording, selectedLanguage);
  });

  /**
   * Listens for messages from other parts of the extension (e.g., popup or background script).
   */
  chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.type === 'toggleRecording') {
      const language = request.language || 'en';
      toggleRecording(request.state, language);
      sendResponse({ status: 'Recording state changed.' });
    }
  });
})();