import { PostMessageFetchUrl, PostMessageFetchListener } from '@/bridge/content/postMessage';

const fetchUrlService = async (payload) => {
  const { url, method, body } = payload;

  const fetchUrl = url;

  const payloadFetch = {
    method,
    headers: {
      accept: 'application/json',
      'af-ac-enc-dat': null,
      'af-ac-enc-sz-token': '',
      'content-type': 'application/json',
    },
  };

  if (method === 'POST') {
    payloadFetch.body = JSON.stringify(body);
  }

  const responsive = await fetch(fetchUrl, payloadFetch);

  const json = await responsive.json();

  return json;
};

const listenerFetchData = (callback) => {
  const { fetch: originalFetch } = window;
  window.fetch = async (...args) => {
    const [url, payload] = args;
    const response = await originalFetch(...args);

    if (url.includes('/api/')) {
      const clone = response.clone();

      clone.json().then((json) => {
        callback({
          json,
          url,
          payload,
        });
      });
    }

    return response;
  };
};

const listenerXhrData = (callback) => {
  const OrigOpen = XMLHttpRequest.prototype.open;
  const OrigSend = XMLHttpRequest.prototype.send;

  XMLHttpRequest.prototype.open = function open(method, url, ...rest) {
    this.__atspUrl = typeof url === 'string' ? url : String(url);
    this.__atspMethod = method;

    return OrigOpen.call(this, method, url, ...rest);
  };

  XMLHttpRequest.prototype.send = function send(body) {
    const url = this.__atspUrl || '';

    if (url.includes('/api/')) {
      this.addEventListener('load', () => {
        if (this.status < 200 || this.status >= 300) {
          return;
        }

        try {
          const type = this.responseType;
          const json = type === '' || type === 'text' ? JSON.parse(this.responseText) : this.response;

          callback({
            json,
            url,
            payload: { method: this.__atspMethod, body },
          });
        } catch (error) {
          // non-JSON response — ignore
        }
      });
    }

    return OrigSend.call(this, body);
  };
};

const startService = async () => {
  PostMessageFetchUrl.startHandler(fetchUrlService);

  listenerFetchData((payload) => PostMessageFetchListener.sendMessage(payload));

  listenerXhrData((payload) => PostMessageFetchListener.sendMessage(payload));
};

startService();
