// -----------------------------------------------------------------
// CONFIG
// -----------------------------------------------------------------

const cols = process.stdout.columns
// const rows = process.stdout.rows
const maxStatLength = Math.floor(cols / 4)
const statNameSpacing = 5
const beforeRowSpace = 13
const coloredWords = {
  red: ['lred', 'thanks'],
  cyan: [
    'getveteranpw',
    'pwrequest',
    'getpw',
    'availablepws',
    'login',
    'logout',
  ],
  green: [
    'manual',
    'todos',
    'allquestions',
    'subjectbrowser',
    'contribute',
    'feedback',
    'ranklist',
    'allqr',
    'possibleAnswers',
    'irc',
    'faq',
    '/script',
    'listUserDir',
    'forumEntries',
    'contacts.json',
  ],
  blue: ['isadding', 'ask', 'newUserDir', 'updateQuestion', 'uploadUserFile'],
  magenta: [
    'addPost',
    'tiszai',
    'install',
    'discord',
    'postfeedback',
    'votetodo',
    'registerscript',
    'quickvote',
    'comment',
    'react'
  ],
}
const filterFromDailyStats = [
  'savedQuestions',
  'sio/f',
  'sound/',
  '/img/',
  '.php',
  '/wordpress/',
  '/wp/',
  '/wp-includes/',
  'favicon',
  'robots.txt',
  'ads.txt',
  '/f/',
  '.git',
  'apple-touch-icon',
  '/.env',
  '/userFiles/'
]

// -----------------------------------------------------------------

const fs = require('fs') // eslint-disable-line

const dir = process.argv[2]
if (!dir) {
  console.log('No params')
  process.exit()
}

function getDayIndex(offset) {
  if (!offset) {
    offset = 0
  }

  const date = new Date()
  if (offset) {
    date.setDate(date.getDate() + offset)
  }
  return (
    date.getFullYear() +
    '-' +
    ('0' + (date.getMonth() + 1)).slice(-2) +
    '-' +
    ('0' + date.getDate()).slice(-2)
  )
}

function hr(char) {
  console.log(C('blue') + getLetterNTimes(char || '=', cols) + C())
}

function printHeader(text) {
  hr()
  console.log(C('green') + text + C())
  hr()
}

function C(color) {
  if (color !== undefined) {
    color = color.toLowerCase()
  }

  if (color === 'redbg') {
    return '\x1b[41m'
  }
  if (color === 'bluebg') {
    return '\x1b[44m'
  }
  if (color === 'green') {
    return '\x1b[32m'
  }
  if (color === 'red') {
    return '\x1b[31m'
  }
  if (color === 'yellow') {
    return '\x1b[33m'
  }
  if (color === 'blue') {
    return '\x1b[34m'
  }
  if (color === 'magenta') {
    return '\x1b[35m'
  }
  if (color === 'cyan') {
    return '\x1b[36m'
  }
  return '\x1b[0m'
}

function readJSON(name) {
  return JSON.parse(fs.readFileSync(name, 'utf8'))
}

function tail(text, number) {
  const splitedText = text.split('\n')
  return splitedText.slice(Math.max(splitedText.length - number, 1)).join('\n')
}

function head(text, number) {
  return text
    .split('\n')
    .slice(0, number)
    .join('\n')
}

function countLinesMatching(text, toMatch) {
  let count = 0
  text.split('\n').forEach((line) => {
    if (line.includes(toMatch.toLowerCase())) {
      count++
    }
  })
  return count
}

function readFile(name) {
  if (fs.existsSync(name)) {
    return fs.readFileSync(name, 'utf8')
  }
}

function getLetterNTimes(letter, number) {
  let res = ''
  while (res.length < number) {
    res += letter
  }
  return res
}

function pCols(cols, rowTitles, colorNames, firstRowColor, showDiff) {
  // console.log(cols)
  let maxLength = 0
  cols.forEach((col) => {
    if (col.length > maxLength) {
      maxLength = col.length
    }
  })

  cols.reverse()

  for (let i = 0; i < maxLength; i++) {
    const row = []
    const lastItems = []

    cols
      .forEach((val) => {
        if (!val[i]) {
          row.push(getLetterNTimes(' ', maxStatLength + 5))
          return
        }

        lastItems.push(val[i])
        const keyName = val[i].name || val[i]

        let slicedName = keyName.slice(0, maxStatLength)
        const toColor = colorNames
          ? Object.keys(coloredWords).reduce((acc, key) => {
              const colorArray = coloredWords[key]

              const includes = colorArray.some((colorableIdName) => {
                return keyName
                  .toLowerCase()
                  .includes(colorableIdName.toLowerCase())
              })

              if (includes) {
                return key
              }

              return acc
            }, '')
          : false

        const sep = (i + 1) % 5 === 0 ? '.' : ' '

        while (slicedName.length < maxStatLength) {
          slicedName = slicedName + sep
        }

        let ammount = val[i].val ? val[i].val.toString() : ''
        while (ammount.length < 4) {
          ammount = ammount + ' '
        }

        if (toColor) {
          row.push(C(toColor) + slicedName + ' ' + ammount + C())
        } else {
          row.push(slicedName + ' ' + ammount)
        }
      })

    // ROW TITLE ---------------------------------------------------
    let currRowTitle =
      rowTitles && rowTitles[i]
        ? rowTitles[i]
        : getLetterNTimes(' ', beforeRowSpace)

    while (currRowTitle.length < beforeRowSpace) {
      currRowTitle = currRowTitle + ' '
    }
    currRowTitle = C('blue') + currRowTitle + C()
    // COLORING ----------------------------------------------------
    let res = ''
    if (firstRowColor && i === 0) {
      res =
        currRowTitle +
        C('green') +
        row.join(getLetterNTimes(' ', statNameSpacing)) +
        C()
    } else {
      res = currRowTitle + row.join(getLetterNTimes(' ', statNameSpacing))
    }
    // SHOW DIFF ---------------------------------------------------
    if (showDiff && i !== 0) {
      let diff =
        lastItems[lastItems.length - 1] - lastItems[lastItems.length - 2]
      if (diff > 0) {
        diff = '+' + diff.toString()
      }
      res += C('blue') + diff + C()
    }

    console.log(res)
  }
}

// ------------------------------------------------------------------------------
printHeader('Daily stats')

const dailyStats = readJSON(`${dir}stats/vstats`)
function preProcessDailyStats(obj) {
  const formatted = Object.keys(obj).reduce((acc, key) => {
    const includes = filterFromDailyStats.some((keyword) => {
      return key.toLowerCase().includes(keyword.toLowerCase())
    })
    if (!includes) {
      acc.push({ name: key.replace(/\.html/g, ''), val: obj[key] })
    }
    return acc
  }, [])

  const merged = formatted.reduce((acc, x) => {
    const index = acc.findIndex((y) => {
      return x.name === y.name
    })

    if (index !== -1) {
      acc = acc.map((z, i) => {
        if (i === index) {
          return {
            ...x,
            val: z.val + x.val
          }
        }
        return z
      })
    } else {
      acc.push(x)
    }

    return acc
  }, [])

  return merged.sort((a, b) => {
    if (a.name > b.name) {
      return 1
    } else if (a.name < b.name) {
      return -1
    } else {
      return 0
    }
  })
}

pCols(
  [
    preProcessDailyStats(dailyStats[getDayIndex()]),
    preProcessDailyStats(dailyStats[getDayIndex(-1)]),
    preProcessDailyStats(dailyStats[getDayIndex(-2)]),
  ],
  null,
  true
)

// ------------------------------------------------------------------------------
printHeader('User id test solving')
const userIdTestSolving = readJSON(`${dir}stats/idvstats`)
function preProcessUIdTestSolving(obj, minLength) {
  if (!obj) {
    return '0'
  }
  if (minLength) {
    return Object.keys(obj)
      .filter((key) => {
        return obj[key] > minLength
      })
      .length.toString()
  } else {
    return Object.keys(obj).length.toString()
  }
}

pCols(
  [
    ['Today', preProcessUIdTestSolving(userIdTestSolving[getDayIndex()])],
    ['Yesterday', preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-1)])],
    [
      'Before yesterday',
      preProcessUIdTestSolving(userIdTestSolving[getDayIndex(-2)]),
    ],
  ],
  null,
  false,
  'green'
)

// ------------------------------------------------------------------------------
printHeader('User id requests')
const clientIdTestSolving = readJSON(`${dir}stats/uvstats`)

pCols(
  [
    [
      'Today',
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex()]),
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex()], 2),
    ],
    [
      'Yesterday',
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-1)]),
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-1)], 2),
    ],
    [
      'Before Yesterday',
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-2)]),
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(-2)], 2),
    ],
  ],
  ['', 'All', 'More than 2'],
  false,
  'green'
)

// ------------------------------------------------------------------------------
printHeader('Daily data count')
const dailyDataCount = readFile(`${dir}stats/dailyDataCount`)

printLastDataCount([
  JSON.parse(head(tail(dailyDataCount, 1), 1)),
  JSON.parse(head(tail(dailyDataCount, 2), 1)),
  JSON.parse(head(tail(dailyDataCount, 3), 1)),
])

function printLastDataCount(data) {
  const res = [['Today'], ['Yesterday'], ['Before yesterday']]
  data.forEach((dataCount, i) => {
    res[i].push(dataCount.userCount.toString())
    res[i].push(dataCount.subjectCount.toString())
    res[i].push(dataCount.questionCount.toString())
  })

  pCols(res, ['', 'Users', 'Subjects', 'Questions'], false, 'green', true)
}
// ------------------------------------------------------------------------------
printHeader('Daily script install / update check count')
const todaysLogs = readFile(`${dir}stats/vlogs/log`)
const yesterdaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex(-1)}`) || ''
const beforeYesterdaysLogs = readFile(`${dir}stats/vlogs/${getDayIndex(-2)}`) || ''

const installs = [
  [
    'Today',
    countLinesMatching(todaysLogs, '?install').toString(),
    countLinesMatching(todaysLogs, '?up').toString(),
  ],
  [
    'Yesterday',
    countLinesMatching(yesterdaysLogs, '?install').toString(),
    countLinesMatching(yesterdaysLogs, '?up').toString(),
  ],
  [
    'Before yesterday',
    countLinesMatching(beforeYesterdaysLogs, '?install').toString(),
    countLinesMatching(beforeYesterdaysLogs, '?up').toString(),
  ],
]

pCols(installs, ['', 'Installs', 'Updates'], false, 'green')