import { JSDOM } from 'jsdom'
import fetch, { Headers } from 'node-fetch'

const config = {
  google: {
    inputQuery: ["input[name='q']", "textarea[name='q']"],
    sidebarContainerQuery: ['#rhs'],
    appendContainerQuery: ['#rcnt'],
    resultsContainerQuery: ['#rso'],
  },
  bing: {
    inputQuery: ["[name='q']"],
    sidebarContainerQuery: ['#b_context'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#b_results'],
  },
  yahoo: {
    inputQuery: ["input[name='p']"],
    sidebarContainerQuery: ['#right', '.Contents__inner.Contents__inner--sub'],
    appendContainerQuery: ['#cols', '#contents__wrap'],
    resultsContainerQuery: [
      '#main-algo',
      '.searchCenterMiddle',
      '.Contents__inner.Contents__inner--main',
      '#contents',
    ],
  },
  duckduckgo: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.js-react-sidebar', '.react-results--sidebar'],
    appendContainerQuery: ['#links_wrapper'],
    resultsContainerQuery: ['.react-results--main'],
  },
  startpage: {
    inputQuery: ["input[name='query']"],
    sidebarContainerQuery: ['.layout-web__sidebar.layout-web__sidebar--web'],
    appendContainerQuery: ['.layout-web__body.layout-web__body--desktop'],
    resultsContainerQuery: ['.mainline-results'],
  },
  baidu: {
    inputQuery: ["input[id='kw']"],
    sidebarContainerQuery: ['#content_right'],
    appendContainerQuery: ['#container'],
    resultsContainerQuery: ['#content_left', '#results'],
  },
  kagi: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.right-content-box._0_right_sidebar'],
    appendContainerQuery: ['#_0_app_content'],
    resultsContainerQuery: ['#main', '#app'],
  },
  yandex: {
    inputQuery: ["input[name='text']"],
    sidebarContainerQuery: ['#search-result-aside'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#search-result'],
  },
  naver: {
    inputQuery: ["input[name='query']"],
    sidebarContainerQuery: ['#sub_pack'],
    appendContainerQuery: ['#content'],
    resultsContainerQuery: ['#main_pack', '#ct'],
  },
  brave: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['#side-right'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#results'],
  },
  searx: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['#sidebar_results', '#sidebar'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#urls', '#main_results', '#results'],
  },
  ecosia: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.sidebar.web__sidebar'],
    appendContainerQuery: ['#main'],
    resultsContainerQuery: ['.mainline'],
  },
  neeva: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.result-group-layout__stickyContainer-iDIO8'],
    appendContainerQuery: ['.search-index__searchHeaderContainer-2JD6q'],
    resultsContainerQuery: ['.result-group-layout__component-1jzTe', '#search'],
  },
}

const urls = {
  google: ['https://www.google.com/search?q=hello'],
  bing: ['https://www.bing.com/search?q=hello'],
  yahoo: ['https://search.yahoo.com/search?p=hello', 'https://search.yahoo.co.jp/search?p=hello'],
  duckduckgo: [],
  startpage: [], // need redirect and post https://www.startpage.com/do/search?query=hello
  baidu: ['https://www.baidu.com/s?wd=hello'],
  kagi: [], // need login https://kagi.com/search?q=hello
  yandex: [], // need cookie https://yandex.com/search/?text=hello
  naver: ['https://search.naver.com/search.naver?query=hello'],
  brave: ['https://search.brave.com/search?q=hello'],
  searx: ['https://searx.tiekoetter.com/search?q=hello'],
  ecosia: [], // unknown verify method https://www.ecosia.org/search?q=hello
  neeva: [], // unknown verify method(FetchError: maximum redirect reached) https://neeva.com/search?q=hello
}

const commonHeaders = {
  Accept:
    'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
  Connection: 'keep-alive',
  'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', // for baidu
}

const desktopHeaders = new Headers({
  'User-Agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/108.0.1462.76',
  ...commonHeaders,
})

const mobileHeaders = {
  'User-Agent':
    'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36 Edg/108.0.1462.76',
  ...commonHeaders,
}

const desktopQueryNames = [
  'inputQuery',
  'sidebarContainerQuery',
  'appendContainerQuery',
  'resultsContainerQuery',
]

const mobileQueryNames = ['inputQuery', 'resultsContainerQuery']

let errors = ''

async function verify(errorTag, urls, headers, queryNames) {
  await Promise.all(
    Object.entries(urls).map(([siteName, urlArray]) =>
      Promise.all(
        urlArray.map((url) =>
          fetch(url, {
            method: 'GET',
            headers: headers,
          })
            .then((response) => response.text())
            .then((text) => {
              const dom = new JSDOM(text)
              for (const queryName of queryNames) {
                const queryArray = config[siteName][queryName]
                if (queryArray.length === 0) continue

                let foundQuery
                for (const query of queryArray) {
                  const element = dom.window.document.querySelector(query)
                  if (element) {
                    foundQuery = query
                    break
                  }
                }
                if (foundQuery) {
                  console.log(`${siteName} ${url} ${queryName}: ${foundQuery} passed`)
                } else {
                  const error = `${siteName} ${url} ${queryName} failed`
                  errors += errorTag + error + '\n'
                }
              }
            })
            .catch((error) => {
              errors += errorTag + error + '\n'
            }),
        ),
      ),
    ),
  )
}

async function main() {
  console.log('Verify desktop search engine configs:')
  await verify('desktop: ', urls, desktopHeaders, desktopQueryNames)
  console.log('\nVerify mobile search engine configs:')
  await verify('mobile: ', urls, mobileHeaders, mobileQueryNames)

  if (errors.length > 0) throw new Error('\n' + errors)
  else console.log('\nAll passed')
}

main()
