const bbUrlPrefix = 'https://git.add123.com/rest/api/latest'

let updateEmptySection

const pullRequestHasErrored = async pr => {
  const latestCommitId = pr?.fromRef?.latestCommit
  if (!latestCommitId) {
    return false
  }
  const buildStats = await fetch(`https://git.add123.com/rest/build-status/latest/commits/stats/${latestCommitId}`).then(resp => resp.json())
  return buildStats.failed !== 0
}

const getAllRepos = async () => {
  const allProjects = (await fetch(`${bbUrlPrefix}/projects`).then(resp => resp.json())).values
  const allProjectKeys = allProjects.map(project => project.key)
  let allRepos = await Promise.all(allProjectKeys.map(async key =>
    await fetch(`${bbUrlPrefix}/projects/${key}/repos?limit=999`)
      .then(resp => resp.json()).then(({ values }) => values)))
  allRepos = allRepos.flatMap(a => a)
  return allRepos
}

const getErroredPrs = async () => {
  const allPullRequests = (await getAllRepos()
    .then(async allRepos => {
      const prListUrls = allRepos.map(repo => `${bbUrlPrefix}/projects/ADD/repos/${repo.slug}/pull-requests`)
      return (await Promise.all(
          prListUrls.map(async prListUrl => await fetch(prListUrl).then(resp => resp.json())))
      ).flatMap(({values}) => values)
    }).catch(console.error)).filter(Boolean)
  const erroredPullRequests = []
  const dismissedCommitIds = getLocalStorage().dismissedCommitIds ?? []
  for (const pullRequest of allPullRequests) {
    if (!dismissedCommitIds.includes(pullRequest?.fromRef?.latestCommit) && await pullRequestHasErrored(pullRequest)) {
      erroredPullRequests.push(pullRequest)
    }
  }
  return erroredPullRequests
}

const getElementAfterErrorList = mainPanel => {
  for (const child of mainPanel.children) {
    if (child.innerHTML.includes('Recently closed pull requests')) {
      return child
    }
  }
  return mainPanel.children[1]
}

const getLocalStorage = () => {
  return JSON.parse(localStorage.getItem('bb-addon-data') ?? '{}')
}

const setLocalStorage = data => {
  localStorage.setItem('bb-addon-data', JSON.stringify(data))
}

const addLocalStorage = data => {
  localStorage.setItem('bb-addon-data', JSON.stringify({
    ...getLocalStorage(),
    ...data
  }))
}

const prErrorTableId = 'bb-addon-error-table'
const prEmptySectionId = 'bb-addon-empty-section'

const configureEmptySection = (loading, emptyState) => {
  const message = loading ? 'Loading PRs with errors...' : 'No pull requests have errors!'
  emptyState.id = prEmptySectionId
  emptyState.className = 'empty-state'
  emptyState.innerHTML = `
      <div className="dashboard-empty-reviewing">
        <p className="dashboard-empty-title" style="font-weight: 500">${message}</p>
        ${loading ? '' : '<p className="dashboard-empty-description"><em>Pray it stays that way.</em></p>'}
      </div>
  `
  return emptyState
}

const buildErrorListTable = () => {
  const table = document.createElement('table')
  table.id = prErrorTableId

  const thead = document.createElement('thead')
  table.appendChild(thead)

  const tr = document.createElement('tr')
  thead.appendChild(tr)

  const summaryColumn = document.createElement('th')
  summaryColumn.className = 'summary-column'
  summaryColumn.colSpan = 6
  tr.appendChild(summaryColumn)

  const reviewersColumn = document.createElement('th')
  reviewersColumn.className = 'reviewers-column'
  reviewersColumn.innerHTML = '&nbsp;'
  tr.appendChild(reviewersColumn)

  const buildsColumn = document.createElement('th')
  buildsColumn.className = 'builds-column'
  buildsColumn.innerHTML = '&nbsp;'
  tr.appendChild(buildsColumn)
  return table
}

const buildPrRow = (pr, parent) => {
  const row = document.createElement('tr')
  row.className = 'pull-request-row'

  const avatar = document.createElement('td')
  avatar.className = 'avatar-column'
  avatar.innerHTML = `
    <div class="user-avatar author-avatar">
      <div style="display: inline-block; position: relative; outline: 0px;">
          <span class="css-1dyoea">
              <span style="background-image: url('/users/${pr.author.user.name}/avatar.png?s=64'); border-radius: 50%;"
              role="img" aria-label="${pr.author.user.name}" class="css-ob4lje"></span>
          </span>
      </div>
    </div>
  `
  row.appendChild(avatar)

  const summaryColumn = document.createElement('td')
  summaryColumn.className = 'summary-column'
  row.appendChild(summaryColumn)

  const prSummary = document.createElement('div')
  prSummary.className = 'pr-summary'
  summaryColumn.appendChild(prSummary)

  const title = document.createElement('div')
  title.className = 'title'
  prSummary.appendChild(title)

  const link = document.createElement('a')
  link.href = pr.links.self[0].href
  link.innerText = pr.title
  title.appendChild(link)

  const details = document.createElement('div')
  details.className = 'details'
  prSummary.appendChild(details)
  details.innerHTML = `
  <span class="user-name details-item">${pr.author.user.displayName}</span>
  <span class="details-item">-</span>
  <span class="details-item pr-id">#${pr.id}</span>
  <span class="details-item pr-project-repo">${pr.toRef.repository.project.name} / ${pr.toRef.repository.name}</span>
  <span class="ref-lozenge details-item" data-project-key="${pr.toRef.repository.project.key}" data-repo-slug="${pr.toRef.repository.name}">
      <span role="presentation">
          <span class="ref-lozenge-content" role="presentation">
              <span>${pr.toRef.displayId}</span>
          </span>
      </span>
  </span>
  `

  const placeholderColumn = document.createElement('td')
  placeholderColumn.className = 'reviewers-column'
  placeholderColumn.innerHTML = 'Dismiss'
  placeholderColumn.addEventListener('click', () => {
    const localStorageData = getLocalStorage()
    localStorageData.dismissedCommitIds ??= []
    localStorageData.dismissedCommitIds.push(pr.fromRef.latestCommit)
    setLocalStorage(localStorageData)
    parent.removeChild(row)
    updateEmptySection(parent.children.length)
  })
  row.appendChild(placeholderColumn)

  const buildColumn = document.createElement('td')
  buildColumn.className = 'build-column'
  buildColumn.innerHTML = '&nbsp'
  row.appendChild(buildColumn)

  return row
}

const showErroredPrs = async () => {
  if (getCurrentUser() !== 'sagevaillancourt') {
    return
  }
  const mainPanel = document.getElementsByClassName('main-panel')[0]
  let prErrorSection = document.getElementById('bb-addon-pr-error-section')
  const emptySection = document.getElementById(prEmptySectionId) ?? document.createElement('div')
  emptySection.id = prEmptySectionId
  let errorList = document.getElementById('bb-addon-pr-error-list')
  const table = document.getElementById(prErrorTableId) ?? buildErrorListTable()

  if (!prErrorSection) {
    prErrorSection = mainPanel.getElementsByClassName('closed-pull-requests')[0].cloneNode()
    prErrorSection.id = 'bb-addon-pr-error-section'

    const header = document.createElement('h3')
    header.innerText = 'Pull requests with errors'
    prErrorSection.appendChild(header)

    prErrorSection.appendChild(emptySection)
    configureEmptySection(true, emptySection)

    errorList = document.createElement('tbody')

    errorList.id = 'bb-addon-pr-error-list'

    mainPanel.insertBefore(prErrorSection, getElementAfterErrorList(mainPanel))

    table.style.visibility = 'collapse'
    table.appendChild(errorList)
    prErrorSection.appendChild(table)
  }

  const erroredPrs = await getErroredPrs()
  Array.from(errorList.children).forEach(child => errorList.removeChild(child))
  erroredPrs.map(pr => buildPrRow(pr, errorList)).forEach(row => errorList.appendChild(row))
  updateEmptySection = length => {
    if (length) {
      table.style.visibility = 'visible'
      emptySection.style.visibility = 'collapse'
    } else {
      configureEmptySection(false, emptySection)
      table.style.visibility = 'collapse'
      emptySection.style.visibility = 'visible'
    }
  }
  updateEmptySection(erroredPrs.length)
}

if (location.toString().includes('/dashboard')) {
  addFix(() => showErroredPrs().catch(console.error))
  setInterval(() => showErroredPrs().catch(console.error), 1000 * 60 * 2)
}