import { EVENT_NAMES } from '../../constants/define';
import getSelector from '../../utilities/selector';
import { SELECT_TYPES } from './constants';

const BORDER_THICKNESS = 2;
const { EXTRACT_DATA, SELECT_NEXT_PAGE_SELECTOR, SELECT_PAGINATION_SELECTOR } = SELECT_TYPES;
const { ON_UPDATE_SELECTOR } = EVENT_NAMES.CLIENT_RECORDER;

export default class Tracker {
  constructor({ eventLogs = [], eventId, reSelectType = null, onUpdateSelector = () => {} } = {}) {
    this._overlay = null;
    this._selector = null;
    this._element = null;
    this._dimensions = {};
    this.currentSelector = '';
    this.eventLogs = eventLogs;

    this._boundMouseMove = this.mousemove.bind(this);
    this._boundMouseOver = this.mouseover.bind(this);
    this._boundContextMenu = this.contextmenu.bind(this);
    this._boundInitialLoad = this.initialLoad.bind(this);

    this[EXTRACT_DATA] = null;
    // this.paginationSelector = null;
    // this.nextPageSelector = null;
    this[SELECT_PAGINATION_SELECTOR] = null;
    this[SELECT_NEXT_PAGE_SELECTOR] = null;
    this.reSelectType = reSelectType;
    this.eventId = eventId;
    this[ON_UPDATE_SELECTOR] = onUpdateSelector;
  }

  startTracking() {
    if (!this._overlay) {
      this._overlay = document.createElement('div');
      this._overlay.id = 'headless-recorder-shooter';
      this._overlay.style.position = 'fixed';
      this._overlay.style.top = '0px';
      this._overlay.style.left = '0px';
      this._overlay.style.width = '100%';
      this._overlay.style.height = '100%';
      this._overlay.style.pointerEvents = 'none';
      this._overlay.style.zIndex = 2147483646;

      this._selector = document.createElement('div');
      this._selector.id = 'headless-recorder-shooter-outline';
      this._selector.style.position = 'fixed';
      this._overlay?.appendChild(this._selector);
    }

    if (!this._overlay.parentNode) {
      document.body?.appendChild(this._overlay);
      document.body.addEventListener('mousemove', this._boundMouseMove, false);
      document.body.addEventListener('mouseover', this._boundMouseOver, false);
      document.body.addEventListener('contextmenu', this._boundContextMenu, false);
    }
  }

  stopTracking() {
    if (this._overlay) {
      window.document.body.removeChild(this._overlay);
    }
    this._overlay = this._selector = this._element = null;
    this._dimensions = {};
    document.body.removeEventListener('mousemove', this._boundMouseMove, false);
    document.body.removeEventListener('mouseover', this._boundMouseOver, false);
  }

  mouseover(e) {
    this.currentSelector = getSelector(e);
  }

  mousemove(e) {
    let existingExtractSelector = document.querySelector(this[EXTRACT_DATA]);
    let existingPaginationSelector = document.querySelector(this[SELECT_PAGINATION_SELECTOR]);
    let existingNextPageSelector = document.querySelector(this[SELECT_NEXT_PAGE_SELECTOR]);
    if (this.reSelectType === 'all') {
      return;
    }

    if (existingExtractSelector && existingPaginationSelector && existingNextPageSelector) {
      return;
    }

    if (
      this._element !== e &&
      e.target.id !== 'custom-context-menu' &&
      e.target.id !== 'extract-data' &&
      e.target.id !== 'pagination-selector' &&
      e.target.id !== 'next-page-selector' &&
      e.target.id !== 'extract-field'
    ) {
      this._element = e;

      this._dimensions.top = -window.scrollY;
      this._dimensions.left = -window.scrollX;

      let elem = e.target;

      while (elem && elem !== document.body) {
        this._dimensions.top += elem.offsetTop;
        this._dimensions.left += elem.offsetLeft;
        elem = elem.offsetParent;
      }
      this._dimensions.width = this._element.target.offsetWidth;
      this._dimensions.height = this._element.target.offsetHeight;

      if (this._selector) {
        this._selector.style.top = this._dimensions.top - BORDER_THICKNESS + 'px';
        this._selector.style.left = this._dimensions.left - BORDER_THICKNESS + 'px';
        this._selector.style.width = this._dimensions.width + 'px';
        this._selector.style.height = this._dimensions.height + 'px';

        if (existingExtractSelector) {
          if (existingPaginationSelector) {
            this._selector.style.border = `${BORDER_THICKNESS}px dashed green`;
            this._selector.style.background = 'rgba(0, 255, 0, 0.1)';
          } else {
            this._selector.style.border = `${BORDER_THICKNESS}px dashed rgba(0, 0, 255, 0.7)`;
            this._selector.style.background = 'rgba(0, 0, 255, 0.1)'; // Blue
          }
        } else {
          this._selector.style.border = `${BORDER_THICKNESS}px dashed rgba(255, 73, 73, 0.7)`;
          this._selector.style.background = 'rgba(255, 73, 73, 0.1)';
        }
      }
    }
  }

  contextmenu(e) {
    e.preventDefault();
    // Clear any existing context menus
    const existingMenu = document.getElementById('custom-context-menu');
    if (existingMenu) {
      existingMenu.remove();
    }
    // Create context menu
    const contextMenu = document.createElement('div');
    contextMenu.id = 'custom-context-menu';
    contextMenu.style.position = 'fixed';
    contextMenu.style.top = `${e.clientY}px`;
    contextMenu.style.left = `${e.clientX}px`;
    contextMenu.style.backgroundColor = '#ffffff';
    contextMenu.style.border = '1px solid #dddddd';
    contextMenu.style.padding = '5px 10px';
    contextMenu.style.zIndex = 2147483647;
    contextMenu.style.cursor = 'pointer';
    contextMenu.style.fontSize = '14px';
    contextMenu.style.display = 'flex';
    contextMenu.style.flexDirection = 'column';
    contextMenu.style.gap = '10px';

    let existingExtractSelector = document.querySelector(this[EXTRACT_DATA]);
    if (!existingExtractSelector) {
      // Create context menu options
      const option1 = document.createElement('div');
      option1.id = 'extract-data';
      option1.innerText = 'Extract Data';
      option1.dataset.selector = getSelector(this._element);
      option1.style.fontSize = '14px';
      option1.addEventListener('click', (e) => {
        e.stopPropagation(); // prevent triggering window click event
        this.highlightSelector(this._element.target, 'red', 'Extract Data');
        this[EXTRACT_DATA] = getSelector(this._element);
        if (this.reSelectType !== 'all') {
          this[ON_UPDATE_SELECTOR]({
            ...this.getEventLog(),
            selector: this[EXTRACT_DATA],
            paginationSelector: this[SELECT_PAGINATION_SELECTOR],
            nextPageSelector: this[SELECT_NEXT_PAGE_SELECTOR],
          });
        }
        contextMenu.remove();
      });
      contextMenu?.appendChild(option1);
    } else {
      let existingPaginationSelector = document.querySelector(this[SELECT_PAGINATION_SELECTOR]);
      if (!existingPaginationSelector) {
        const option2 = document.createElement('div');
        option2.id = 'pagination-selector';
        option2.innerText = 'Select pagination selector';
        option2.dataset.selector = getSelector(this._element);
        option2.addEventListener('click', (e) => {
        e.stopPropagation(); // prevent triggering window click event
          this.highlightSelector(this._element.target, 'blue', 'Pagination Selector');
          this[SELECT_PAGINATION_SELECTOR] = getSelector(this._element);
          this[ON_UPDATE_SELECTOR]({
            ...this.getEventLog(),
            selector: this[EXTRACT_DATA],
            paginationSelector: this[SELECT_PAGINATION_SELECTOR],
            nextPageSelector: this[SELECT_NEXT_PAGE_SELECTOR],
          });
          contextMenu.remove();
        });
        contextMenu?.appendChild(option2);
      } else {
        const option3 = document.createElement('div');
        option3.id = 'next-page-selector';
        option3.innerText = 'Select Next Page Selector';
        option3.dataset.selector = getSelector(this._element);
        option3.addEventListener('click', (e) => {
          e.stopPropagation(); // prevent triggering window click event
          this.highlightSelector(this._element.target, 'green', 'Next Page Selector');
          this[SELECT_NEXT_PAGE_SELECTOR] = getSelector(this._element);
          if (this.reSelectType !== 'all') {
            // this[ON_UPDATE_SELECTOR](this.reSelectType, this[this.reSelectType]);
            this[ON_UPDATE_SELECTOR]({
              ...this.getEventLog(),
              selector: this[EXTRACT_DATA],
              paginationSelector: this[SELECT_PAGINATION_SELECTOR],
              nextPageSelector: this[SELECT_NEXT_PAGE_SELECTOR],
            });
          }

          contextMenu.remove();
        });
        contextMenu?.appendChild(option3);
      }
    }

    const option4 = document.createElement('div');
    option4.id = 'extract-field';
    option4.innerText = 'Extract Field';
    option4.dataset.selector = getSelector(this._element);
    option4.addEventListener('click', (e) => {
      e.stopPropagation(); // prevent triggering window click event
      this.highlightSelector(this._element.target, 'red', 'Extract Field');
      this[EXTRACT_DATA] = getSelector(this._element);
      contextMenu.remove();
    });
    contextMenu?.appendChild(option4);

    document.body?.appendChild(contextMenu);
  }

  highlightSelector(elementTarget, color, text) {
    elementTarget.style.border = `${BORDER_THICKNESS}px dashed ${color}`;
    if (color === 'red') {
      elementTarget.style.background = 'rgba(255, 73, 73, 0.1)';
    } else if (color === 'blue') {
      elementTarget.style.background = 'rgba(0, 0, 255, 0.1)'; // Blue
    } else if (color === 'green') {
      elementTarget.style.background = 'rgba(0, 255, 0, 0.1)';
    }

    // Make sure the target element's position is not static
    if (window.getComputedStyle(elementTarget).position === 'static') {
      elementTarget.style.position = 'relative';
    }

    const textElement = document.createElement('div');
    textElement.style.position = 'absolute'; // Change from 'relative' to 'absolute'
    textElement.style.top = `-${BORDER_THICKNESS + 20}px`; // position it above the border
    textElement.style.left = `0px`; // align it with the left edge of the border
    textElement.style.color = color;
    textElement.style.zIndex = 2147483647; // to make sure it is on top of everything else
    textElement.textContent = text;
    elementTarget.appendChild(textElement); // Append the text element as a child of the target element
  }

  initialLoad(eventLog) {
    if (eventLog.action === 'extract-data') {
      const { selector, paginationSelector, nextPageSelector } = eventLog;
      const extractElement = selector && document.querySelector(selector);
      const paginationElement = paginationSelector && document.querySelector(paginationSelector);
      const nextPageElement = nextPageSelector && document.querySelector(nextPageSelector);
      if (extractElement) {
        if (this.reSelectType !== SELECT_TYPES.EXTRACT_DATA) {
          this.highlightSelector(extractElement, 'red', `Extract Data (${eventLog?.id}})`);
          this[EXTRACT_DATA] = selector;
        }
      }
      if (paginationElement) {
        if (this.reSelectType !== SELECT_TYPES.SELECT_PAGINATION_SELECTOR) {
          this.highlightSelector(paginationElement, 'blue', `Pagination Selector (${eventLog?.id})`);
          this[SELECT_PAGINATION_SELECTOR] = paginationSelector;
        }
      }
      if (nextPageElement) {
        if (this.reSelectType !== SELECT_TYPES.SELECT_NEXT_PAGE_SELECTOR) {
          this.highlightSelector(nextPageElement, 'green', `Next Page Selector (${eventLog?.id})`);
          this[SELECT_NEXT_PAGE_SELECTOR] = nextPageSelector;
        }
      }
    }
  }

  getEventLog() {
    if (this?.eventId && this.eventLogs?.length > 0) {
      return this.eventLogs?.find((eventLog) => eventLog.id === this.eventId);
    }
  }
}
