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

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

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

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 getDayName(day) {
  switch (day) {
    case 0:
    case undefined:
      return 'Today'
    case -1:
      return 'Yesterday'
    case -2:
      return 'Before yesterday'
    default:
      return `Day ${day.toString()}`
  }
}

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) {
  // console.log(cols)
  let maxLength = 0
  cols.reverse().forEach((col, i) => {
    if (i >= colsToPrint) {
      return
    }
    if (col.length > maxLength) {
      maxLength = col.length
    }
  })

  cols.reverse()

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

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

      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 < 5) {
        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 ---------------------------------------------------
    console.log(res)
  }
}

// ------------------------------------------------------------------------------
printHeader('Daily stats')
try {
  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
      }
    })
  }
  function getDailyStat(day) {
    return preProcessDailyStats(dailyStats[getDayIndex(day)])
  }

  pCols(
    [
      ...[...Array(colsToPrint).keys()].map((x) => {
        return getDailyStat(-x)
      }),
    ],
    null,
    true
  )
} catch (e) {
  console.error(e)
}

// ------------------------------------------------------------------------------
printHeader('User id test solving')
try {
  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()
    }
  }
  function getUserIdTestSolving(day) {
    return [
      getDayName(day),
      preProcessUIdTestSolving(userIdTestSolving[getDayIndex(day)]),
    ]
  }

  pCols(
    [
      ...[...Array(colsToPrint).keys()].map((x) => {
        return getUserIdTestSolving(-x)
      }),
    ],
    null,
    false,
    'green'
  )
} catch(e) {
  console.error(e)
}

// ------------------------------------------------------------------------------
printHeader('User id requests')
try {
  const clientIdTestSolving = readJSON(`${dir}stats/uvstats`)
  function getUserIdRequests(day) {
    return [
      getDayName(day),
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(day)]),
      preProcessUIdTestSolving(clientIdTestSolving[getDayIndex(day)], 5),
    ]
  }

  pCols(
    [
      ...[...Array(colsToPrint).keys()].map((x) => {
        return getUserIdRequests(-x)
      }),
    ],
    ['', 'All', 'More than 5'],
    false,
    'green'
  )

  // ------------------------------------------------------------------------------
  printHeader('Daily data count')
  const dailyDataCount = readFile(`${dir}stats/dailyDataCount`)
  function getDailyDataCount(count) {
    return [...Array(count).keys()].map((x) => {
      return JSON.parse(head(tail(dailyDataCount, x + 1), 1))
    })
  }

  printLastDataCount(getDailyDataCount(colsToPrint))

  function printLastDataCount(data) {
    const res = [...Array(colsToPrint).keys()].map((x) => {
      return [getDayName(-x)]
    })
    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')
  }
} catch(e) {
  console.error(e)
}
// ------------------------------------------------------------------------------
printHeader('Daily script install / update check count')
try {
  function getDailyScriptStat(day) {
    const log =
      !day || day === 0
        ? readFile(`${dir}stats/vlogs/log`)
        : readFile(`${dir}stats/vlogs/${getDayIndex(day)}`)

    if (!log) {
      return [getDayName(day), 0, 0]
    }
    return [
      getDayName(day),
      countLinesMatching(log, '?install').toString(),
      countLinesMatching(log, '?up').toString(),
    ]
  }

  const installs = [...Array(colsToPrint).keys()].map((x) => {
    return getDailyScriptStat(-x)
  })

  pCols(installs, ['', 'Installs', 'Updates'], false, 'green')
} catch(e) {
  console.error(e)
}