const SPECIAL_CHARS_REGEX = /[%:*()]/g;

function openDataBase() {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open("Traducoes", 1);

    request.onerror = () => reject('Erro ao abrir o banco de dados');
    request.onsuccess = () => resolve(request.result);
    request.onupgradeneeded = (e) => { createObjectStore(e) };
  });
}

function createObjectStore(event) {
  const db = event.target.result;

  if (!db.objectStoreNames.contains("translations")) {
    db.createObjectStore("translations", { keyPath: "n" });
  }
}

async function loadTranslation(key) {
  try {
    const db = await openDataBase();
    const transaction = db.transaction("translations", "readonly");
    const store = transaction.objectStore("translations");
    const request = store.get(key);

    return new Promise((resolve, reject) => {
      request.onsuccess = () => {
        db.close();
        resolve(request.result?.t || null)
      }
      request.onerror = () => { 
        db.close();
        reject('Erro ao buscar tradução') 
      }
    });
  } catch (error) {
    console.error('Erro ao carregar traduções:', error);
    return null;
  }
}

function normalizeText(text) {
  return text.normalize("NFD")
    .replace(/\p{Diacritic}/gu, "")
    .replace(/\n/g, '')
    .replace(/\s+/g, ' ')
    .replace(/[^a-zA-Z0-9\s]/g, "")
    .toUpperCase()
    .trim();

}

async function translateText(text) {
  try {
    if (!text || (getCookie("idiomaUsuario") === 'P' || getCookie("idiomaUsuario") === '' || text === '')) return text;

    const translatedSpecificSentence = translateSpecificSentences(text, getCookie("idiomaUsuario"));
    if (translatedSpecificSentence !== '') {
      return translatedSpecificSentence;
    }

    const matchNumber = text.match(/^\d+\./);
    const number = matchNumber ? matchNumber[0] : '';
    let result = number;
    let finalTextLabel = ''
    const porcentageAtTheBeginning = text.indexOf('% ') == 0 ? '% ' : ''

    if (text.length >= 3) {
      finalTextLabel = appliesSpecialChar(text)
    }
    const translateCompleteText = await loadTranslation(normalizeText(text.replaceAll(number, '').trim()));

    if (translateCompleteText && translateCompleteText != text) {
      return result + porcentageAtTheBeginning + translateCompleteText + finalTextLabel || text;
    }

    const parts = text.split(SPECIAL_CHARS_REGEX).filter(Boolean);
    const specials = text.match(SPECIAL_CHARS_REGEX) || [];

    const translatedParts = await Promise.all(
      parts.map(async (part) => {
        if (!part.trim()) return part.replaceAll(number, '');
        const normalized = normalizeText(part.replaceAll(number, '').trim());
        const translation = await loadTranslation(normalized);
        return translation || part;
      })
    );

    for (let i = 0; i < translatedParts.length; i++) {
      result += translatedParts[i].replaceAll(number, '');
      if (specials[i]) result += specials[i];
    }

    return result;
  } catch (err) {
    console.error(err)
  }
}

window.translateSentence = async function (sentence) {
  return await translateText(sentence);
};

window.translateDataTableElement = async function (dataTableInstance) {
  if (getCookie("idiomaUsuario") === 'P' || getCookie("idiomaUsuario") === '') return;

  const $dataTableWrapper = $(dataTableInstance.table().container()).closest('.dataTables_wrapper');

  $dataTableWrapper.find('*').each(async function () {
    const $element = $(this);

    if ($element.attr('title')) {
      translateTitle($element);
    }

    if ($element.is('button')) {
      translateButton($element);
    }

    if ($element.is('a')) {
      translateTextInput($element);
    }

    if ($element.is('table')) {
      await translateColumns(dataTableInstance)
    };
  });
};

window.translateLoginForm = async function (loginForm) {
  const $loginForm = $(loginForm);

  $loginForm.find('*').each(async function () {
    const $element = $(this);

    if ($element.is('h5, label, strong')) {
      translateTextInput($element)
    }

    if ($element.is('button')) {
      translateButton($element);
    }

    if ($element.is('input') && $element.attr('placeholder')) {
      traslatePlaceholder($element);
    }

    if ($element.attr('title')) {
      translateTitle($element);
    }

    if ($element.is('span#select2-rgEmpresa-container')) {
      translateTextInput($element)
    }
  });
};

window.translatePage = async function () {
  if (getCookie("idiomaUsuario") == 'P' || getCookie("idiomaUsuario") == '') {
    return;
  }

  $(document).find('*').each(async function () {
    const $element = $(this);

    if ($element.is("ul") && $element.attr("id") == "menu_esquerda") {
      $element.find(`li > a > p`).each(function () {
        const $elemento = $(this);

        const firstNodeText = $elemento.contents().filter(function () { return this.nodeType === 3 && this.nodeValue.trim() !== '' }).get(0);

        if (firstNodeText) {
          translateNodeValue(firstNodeText);
        }
      });
      return;
    }

    if ($element.is("li") && ($element.attr("id") == "menu_configuracoes" || $element.attr("id") == "menu_logoff")) {
      $element.find('div > a').each(function () {
        const $elemento = $(this);

        let firstNodeText = '';
        if ($elemento.attr('id') == 'zoom') {
          firstNodeText = $elemento.find('span:not(#spanPorcentagem)').contents().filter(function () { return this.nodeType === 3 && this.nodeValue.trim() !== '' }).get(0);
        } else if ($elemento.attr('id') == 'btn-tema') {
          firstNodeText = $elemento.find('span').contents().filter(function () { return this.nodeType === 3 && this.nodeValue.trim() !== '' }).get(0);
        } else {
          firstNodeText = $elemento.contents().filter(function () { return this.nodeType === 3 && this.nodeValue.trim() !== '' }).get(0);
        }

        if (firstNodeText) {
          translateNodeValue(firstNodeText);
        }
      });
      return;
    }

    if ($element.is("div") && $element.attr("id") == "exibir_iframe") {
      $element.find(`div:not(.tab-content) > a`).each(function () {
        const $elemento = $(this);

        const firstNodeText = $elemento.contents().filter(function () { return this.nodeType === 3 && this.nodeValue.trim() !== '' }).get(0);

        if (firstNodeText) {
          translateNodeValue(firstNodeText);
        }
      });
      return;
    }

    if ($element.attr('class') == 'float-button') {
      $element.find('button#show-content > span').each(function () {
        const $elemento = $(this)

        translateTextInput($elemento)
      })
      $element.find('div#content > div > div#opcoes-widget').find('*').each(async function () {
        const $elemento = $(this)

        const firstNodeText = $elemento.contents().filter(function () { return this.nodeType === 3 && this.nodeValue.trim() !== '' }).get(0);

        if (firstNodeText) {
          await translateNodeValue(firstNodeText);
        }

        if ($elemento.attr('placeholder')) {
          traslatePlaceholder($elemento);
        }
      })
      $element.find('div#content > div > div:not(#opcoes-widget)').find('*').each(async function () {
        const $elemento = $(this);

        if ($elemento.is('div.col-sm-12') && $elemento.css('border-style') === 'dashed') {
          const ifYouNeed = await translateSentence('Se precisar de');
          const support = await translateSentence('Suporte')
          const forAnyQuestion = await translateSentence('para quaisquer questões')
          const call = await translateSentence('Ligue para')
          const text = `${ifYouNeed} <b>${support}</b> ${forAnyQuestion}<br/> ${call}: <b>(47) 3380-6100.</b>`

          $elemento.html(text);
        }
      });
      $element.find('div#content > div > header').find('*').each(async function () {
        const $elemento = $(this);

        if ($elemento.attr('id') == 'titleFeedback') {
          await translateTextInput($elemento)
        }

        if ($elemento.is('button') && $elemento.attr('title')) {
          const tituloOriginal = $elemento.attr('title');
          const tituloTraduzido = await translateText(tituloOriginal) || tituloOriginal;
          $elemento.attr('title', tituloTraduzido);
        }
      });
    }

    if ($element.is('h1, h2, h3, h4, h5, h6, label, strong, p, a, b, span, legend')) {
      translateTextInput($element)
    }

    if ($element.is('button')) {
      translateButton($element);
    }

    if ($element.attr('placeholder')) {
      traslatePlaceholder($element);
    }

    if ($element.attr('data-original-title')) {
      translateDataOriginalTitle($element)
    }

    if ($element.attr('title')) {
      translateTitle($element);
    }

    if ($element.is('input') && $element.attr('value') != '') {
      translateInputButton($element)
    }

    if ($element.is('select')) {
      translateTextInput($element)
      $element.find('option').each(async function () {
        const $option = $(this);
        const textoAtual = $option.text().trim();
        const textoTraduzido = await translateText(textoAtual) || textoAtual;

        $option.text(textoTraduzido);
        $option.val($option.val());
      });
      return;
    }

    if ($element.is('div')) {
      $element.find('h1').each(async function () {
        const $elemento = $(this)

        translateTextInput($elemento)
      })

      return;
    }

  });
};

//////// traduções dos componentes

async function translateButton($element) {
  const texto = $element.contents().filter(function () {
    return this.nodeType === 3 && !$(this).parent().is('span');
  }).text().trim();
  const translateTexto = await translateText(texto) || texto;
  $element.contents().filter(function () {
    return this.nodeType === 3 && !$(this).parent().is('span') && $(this).text().trim() !== '';
  }).each(function () {
    this.nodeValue = translateTexto;
  });
  return;
}

async function translateInputButton($element) {
  const originalValue = $element.attr('value')
  const translatedValue = await translateText(originalValue) || originalValue
  $element.attr('value', translatedValue)
}

async function traslatePlaceholder($element) {
  const originalPlaceholder = $element.attr('placeholder');
  const translatedPlaceholder = await translateText(originalPlaceholder) || originalPlaceholder;
  $element.attr('placeholder', translatedPlaceholder);
  return;
}

async function translateTitle($element) {
  const originalTitle = $element.attr('title');
  const translatedTitle = await translateText(originalTitle) || originalTitle;
  $element.attr('title', translatedTitle);
  return;
}

async function translateDataOriginalTitle($element) {
  const originalTitle = $element.attr('data-original-title');
  const translatedTitle = await translateText(originalTitle) || originalTitle;
  $element.attr('data-original-title', translatedTitle);
  return;
}

async function translateNodeValue(firstNodeText) {
  const textoAtual = firstNodeText.nodeValue.trim();
  const textoTraduzido = await translateText(textoAtual) || textoAtual;
  firstNodeText.nodeValue = textoTraduzido;
}

async function translateTextInput($element) {
  if ($element.hasClass('info-box-number')) return
  const texto = $element.contents().filter(function () {
    return this.nodeType === 3;
  }).text().trim();
  const translateTexto = await translateText(texto) || texto;
  if (translateTexto !== texto) {
    $element.contents().filter(function () {
      return this.nodeType === 3;
    }).get(0).nodeValue = translateTexto;

    $element.contents().filter(function () {
      return this.nodeType === 3;
    }).slice(1).remove();
  }
  return;
}

async function translateColumns(dataTableInstance) {
  const table = dataTableInstance.table();
  const headerCells = $(table.header()).find("th");

  for (const th of headerCells) {
    const $th = $(th);
    const texto = $th.text().trim();
    const translateTexto = await translateText(texto) || texto;
    $th.text(translateTexto);
  }
}

function appliesSpecialChar(text) {
  const porcentageAtTheEnd = text.indexOf('% ') == text.length - 1
  const asteriskAtTheEnd = text.indexOf('*') == text.length - 1
  const twoPointAtTheEnd = text.indexOf(':') == text.length - 1
  const twoPointAndAsteristic = text.indexOf(': *') == text.length - 3
  const twoPointAndPorcentage = text.indexOf(': %') == text.length - 3
  const porcentageAndTwoPoint = text.indexOf('%:') == text.length - 2

  return twoPointAndAsteristic ? ': *' : asteriskAtTheEnd ? ' *' : porcentageAndTwoPoint ? ' %:' : twoPointAtTheEnd ? ':' : twoPointAndPorcentage ? ': %' : porcentageAtTheEnd ? ' %' : ''
}

function translateSpecificSentences(text, language) {
  const specificTranslations = {
    'Aqui estão os campos disponíveis para o cadastro, os campos obrigatórios terão o * ao lado do nome.': {
      I: 'Here are the fields available for registration, mandatory fields will have * next to the name.',
      E: 'Estos son los campos disponibles para el registro, los campos obligatorios tendrán * al lado del nombre.',
      M: '以下是可用于注册的字段，必填字段的名称旁边会有 *。'
    },
    'Esse é um campo obrigatório, para identificá-los, você verá um * ao lado do nome.': {
      I: 'This is a mandatory field, to identify them, you will see a * next to the name.',
      E: 'Este es un campo obligatorio, para identificarlos, verás un * junto al nombre.',
      M: '这是一个必填字段，要识别它们，您会在名称旁边看到 *。'
    },
    'Ao alterar esse campo, será feita uma pesquisa aos WebServices https://apps.correios.com.br/ e http://viacep.com.br/ws/, se houver retorno preencherá os campos de endereço.': {
      I: 'When changing this field, a search will be made to the WebServices https://apps.correios.com.br/ and http://viacep.com.br/ws/, and if there is a response, the address fields will be filled.',
      E: 'Al cambiar este campo, se realizará una búsqueda en los WebServices https://apps.correios.com.br/ y http://viacep.com.br/ws/, y si hay respuesta, se completarán los campos de dirección.',
      M: '更改此字段时，将查询 WebServices https://apps.correios.com.br/ 和 http://viacep.com.br/ws/，如果有返回结果，将填写地址字段。'
    },
    'Ao alterar esse campo, será feita uma pesquisa ao WebService https://www.receitaws.com.br/ e se houver retorno preencherá os campos básicos do cadastro.': {
      I: 'When changing this field, a search will be made to the WebService https://www.receitaws.com.br/, and if there is a response, the basic registration fields will be filled.',
      E: 'Al cambiar este campo, se realizará una búsqueda en el WebService https://www.receitaws.com.br/ y si hay respuesta, se completarán los campos básicos del registro.',
      M: '更改此字段时，将查询 WebService https://www.receitaws.com.br/，如果有返回结果，将填写基本注册字段。'
    },
    'Esse é um campo obrigatório, para identificá-los, você verá um * ao lado do nome, ele serve para descrever a Aplicação do PCP cadastrado ou uma nova Aplicação.': {
      I: "This is a required field, to identify them, you will see a * next to the name, it serves to describe the registered PCP Application or a new Application.",
      E: "Este es un campo obligatorio, para identificarlos, verás un * al lado del nombre, sirve para describir la Aplicación del PCP registrada o una nueva Aplicación.",
      M: "这是一个必填字段，您将看到名称旁边有一个 *, 它用于描述已注册的PCP应用程序或一个新的应用程序。"
    },
    "Esse é um campo obrigatório, para identificá-los, você verá um * ao lado do nome, ele serve para descrever o Tipo Fiscal cadastrado ou o novo cadastro.": {
      "I": "This is a required field. To identify them, you will see an * next to the name, which is used to describe the registered Fiscal Type or the new registration.",
      "E": "Este es un campo obligatorio. Para identificarlos, verá un * junto al nombre, que se utiliza para describir el Tipo Fiscal registrado o el nuevo registro.",
      "M": "这是一个必填字段。要识别它们，您将在名称旁边看到一个 *，用于描述已注册的税种或新的注册。"
    }
  }

  return specificTranslations[text]?.[language] || ''
}