import { record } from 'rrweb';
import { ContentLogger } from '../shared/logger';
import type { UserEvent } from '../shared/types';

interface RrwebEventsResponse {
  events: EventWithTime[];
  userEvents: UserEvent[];
}

type EventWithTime = any;

const logger = new ContentLogger('Main');

// Константы
const RRWEB_MAX_EVENTS = 5000;
const RRWEB_RETENTION_MS = 10 * 60 * 1000; // 10 минут
const USER_EVENT_RETENTION_MS = 10 * 60 * 1000; // 10 минут
const CLEANUP_INTERVAL_MS = 60 * 1000; // 1 минута

// Буфер rrweb событий
let rrwebEvents: EventWithTime[] = [];

// Буфер пользовательских событий
let userEvents: UserEvent[] = [];

// Очистка старых событий
function cleanupOldEvents() {
  const now = Date.now();

  // Очистка rrweb событий
  const rrwebBeforeCount = rrwebEvents.length;
  rrwebEvents = rrwebEvents.filter(event => {
    return (now - event.timestamp) < RRWEB_RETENTION_MS;
  });
  logger.log(`rrweb cleanup: ${rrwebBeforeCount} -> ${rrwebEvents.length} events`);

  // Если все равно слишком много событий, удаляем самые старые
  if (rrwebEvents.length > RRWEB_MAX_EVENTS) {
    const toRemove = rrwebEvents.length - RRWEB_MAX_EVENTS;
    rrwebEvents = rrwebEvents.slice(toRemove);
    logger.log(`rrweb limit exceeded, removed ${toRemove} oldest events`);
  }

  // Очистка пользовательских событий
  const userBeforeCount = userEvents.length;
  userEvents = userEvents.filter(event => {
    return (now - event.timestamp) < USER_EVENT_RETENTION_MS;
  });
  logger.log(`user events cleanup: ${userBeforeCount} -> ${userEvents.length} events`);
}

// Добавление пользовательского события
function addUserEvent(event: UserEvent) {
  event.timestamp = Date.now();
  event.url = window.location.href;
  userEvents.push(event);
  logger.log(`User event: ${event.type}`, event);
}

// Логирование кликов
function setupClickLogging() {
  document.addEventListener('click', (event) => {
    const target = event.target as HTMLElement;
    const selector = getSelector(target);

    addUserEvent({
      timestamp: Date.now(),
      type: 'click',
      target: selector,
      value: target.textContent?.substring(0, 100) || '',
      url: window.location.href
    });
  }, true);
}

// Логирование ввода (без паролей)
function setupInputLogging() {
  document.addEventListener('input', (event) => {
    const target = event.target as HTMLInputElement;

    // Пропускаем пароли
    if (target.type === 'password') {
      return;
    }

    const selector = getSelector(target);

    addUserEvent({
      timestamp: Date.now(),
      type: 'input',
      target: selector,
      value: target.value.substring(0, 200), // Ограничиваем длину
      url: window.location.href
    });
  }, true);
}

// Логирование навигации
function setupNavigationLogging() {
  const handleNavigation = () => {
    addUserEvent({
      timestamp: Date.now(),
      type: 'navigation',
      target: 'window',
      value: window.location.href,
      url: window.location.href,
      meta: { previousUrl: history.state?.url || 'unknown' }
    });
  };

  window.addEventListener('popstate', handleNavigation);
  window.addEventListener('hashchange', handleNavigation);

  // Интерсепт History API
  // @ts-ignore
  const originalPushState = history.pushState;
  // @ts-ignore
  const originalReplaceState = history.replaceState;

  // @ts-ignore
  history.pushState = function(...args) {
    originalPushState.apply(this, args);
    handleNavigation();
  };
  // @ts-ignore
  history.replaceState = function(...args) {
    originalReplaceState.apply(this, args);
    handleNavigation();
  };
}

// Логирование JS ошибок
function setupErrorLogging() {
  window.addEventListener('error', (event) => {
    addUserEvent({
      timestamp: Date.now(),
      type: 'js_error',
      target: event.filename || 'unknown',
      value: event.message,
      url: window.location.href,
      meta: {
        line: event.lineno,
        column: event.colno,
        stack: event.error?.stack
      }
    });
  });

  window.addEventListener('unhandledrejection', (event) => {
    addUserEvent({
      timestamp: Date.now(),
      type: 'js_error',
      target: 'unhandledrejection',
      value: event.reason?.toString() || 'Unknown rejection',
      url: window.location.href,
      meta: {
        promise: event.promise.toString()
      }
    });
  });
}

// Логирование сетевых ошибок
function setupNetworkLogging() {
  // Перехват fetch
  const originalFetch = window.fetch;
  window.fetch = function(...args) {
    return originalFetch.apply(this, args)
      .then(response => {
        if (!response.ok) {
          addUserEvent({
            timestamp: Date.now(),
            type: 'network_error',
            target: args[0]?.toString() || 'unknown',
            value: `HTTP ${response.status} ${response.statusText}`,
            url: window.location.href,
            meta: {
              status: response.status,
              statusText: response.statusText,
              url: response.url
            }
          });
        }
        return response;
      })
      .catch(error => {
        addUserEvent({
          timestamp: Date.now(),
          type: 'network_error',
          target: args[0]?.toString() || 'unknown',
          value: error.message,
          url: window.location.href,
          meta: {
            errorType: error.name
          }
        });
        throw error;
      });
  };

  // Перехват XMLHttpRequest
  // @ts-ignore
  const originalXHROpen = XMLHttpRequest.prototype.open;
  // @ts-ignore
  const originalXHRSend = XMLHttpRequest.prototype.send;

  // @ts-ignore
  XMLHttpRequest.prototype.open = function(...args) {
    (this as any)._method = args[0];
    (this as any)._url = args[1];
    // @ts-ignore
    return originalXHROpen.apply(this, args);
  };

  // @ts-ignore
  XMLHttpRequest.prototype.send = function(...args) {
    this.addEventListener('loadend', function() {
      const xhr = this as XMLHttpRequest;
      if (xhr.status >= 400 || xhr.status === 0) {
        addUserEvent({
          timestamp: Date.now(),
          type: 'network_error',
          target: (xhr as any)._url || 'unknown',
          value: `HTTP ${xhr.status} ${xhr.statusText || 'Network Error'}`,
          url: window.location.href,
          meta: {
            method: (xhr as any)._method,
            status: xhr.status,
            statusText: xhr.statusText
          }
        });
      }
    });
    // @ts-ignore
    return originalXHRSend.apply(this, args);
  };
}

// Получение CSS селектора элемента
function getSelector(element: HTMLElement): string {
  if (element.id) {
    return `#${element.id}`;
  }

  const parts: string[] = [];
  let current: HTMLElement | null = element;

  while (current && current.nodeType === Node.ELEMENT_NODE) {
    if (current.id) {
      parts.unshift(`#${current.id}`);
      break;
    } else {
      let tagName = current.tagName.toLowerCase();
      if (current === element) {
        // Для целевого элемента берем точный путь
        parts.unshift(tagName);
      } else {
        let siblingIndex = 0;
        let sibling = current.previousSibling;
        while (sibling) {
          if (sibling.nodeType === Node.ELEMENT_NODE &&
              (sibling as HTMLElement).tagName === current.tagName) {
            siblingIndex++;
          }
          sibling = sibling.previousSibling;
        }
        if (siblingIndex > 0) {
          parts.unshift(`${tagName}:nth-of-type(${siblingIndex + 1})`);
        } else {
          parts.unshift(tagName);
        }
      }
      current = current.parentElement;
    }

    if (parts.length >= 5) {
      break;
    }
  }

  return parts.join(' > ');
}

// Инициализация rrweb
function initRrweb() {
  record({
    emit(event) {
      rrwebEvents.push(event);
    },
    maskInputOptions: {
      color: false,
      date: false,
      'datetime-local': false,
      email: false,
      month: false,
      number: false,
      range: false,
      search: false,
      tel: false,
      text: false,
      time: false,
      url: false,
      week: false,
      textarea: false,
      select: false,
      password: true, // Маскируем только пароли
    },
    maskTextSelector: '[data-sensitive="true"]',
  });

  logger.log('rrweb recorder initialized');
}

// Обработка сообщений от Service Worker
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
  logger.log('Received message:', message);

  if (message.type === 'GET_RRWEB_EVENTS') {
    const response: RrwebEventsResponse = {
      events: rrwebEvents,
      userEvents: userEvents
    };
    logger.log(`Sending ${rrwebEvents.length} rrweb events and ${userEvents.length} user events`);
    sendResponse(response);
    return true;
  }

  return false;
});

// Запуск
logger.log('Content script starting');

// Ждем готовности DOM
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', start);
} else {
  start();
}

function start() {
  logger.log('Starting content script on:', window.location.href);

  // Инициализация rrweb
  initRrweb();

  // Настройка логирования
  setupClickLogging();
  setupInputLogging();
  setupNavigationLogging();
  setupErrorLogging();
  setupNetworkLogging();

  // Запуск очистки старых событий
  setInterval(cleanupOldEvents, CLEANUP_INTERVAL_MS);

  logger.log('Content script initialized');
}