const { commas, quackGradeMultiplier, prestigeMultiplier, makeBackup, userHasCheckedQuackgrade, getUser, saveUser } = require('./utils')
const { quackStore } = require('./quackstore')
const buyableItems = require('./buyableItems')
const slack = require('../../slack')

const possiblePrestige = coins => {
  let p = 0
  while (totalCostForPrestige(p + 1) <= coins) {
    p += 1
  }
  return p
}

const tpcRecMemo = []
const totalCostForPrestige = prestigeLevel => {
  if (prestigeLevel === 0) {
    return 0
  }
  return (tpcRecMemo[prestigeLevel]) || (tpcRecMemo[prestigeLevel] = 1_000_000_000_000 * Math.pow(prestigeLevel, 3) + totalCostForPrestige(prestigeLevel - 1))
}

const prestigeRoute = async ({ say, args, user }) => {
  const possible = possiblePrestige(user.coinsAllTime)
  const current = user.prestige ??= 0
  if (args[0] === 'me') {
    await say(
      'This will permanently remove all of your items, upgrades, and coins!\n\n' +
            'Say \'!!prestige me\' to confirm.'
    )
  } else {
    const currentCost = totalCostForPrestige(possible)
    const nextCost = totalCostForPrestige(possible + 1)
    const diff = nextCost - currentCost
    const progress = user.coinsAllTime - currentCost
    const bars = Math.round((progress / diff) * 10)
    const empty = 10 - bars
    const progressBar = '[' + '='.repeat(bars) + ' '.repeat(empty) + ']'
    await say(
      `Current Prestige: ${commas(current)}\n\n` +
      `Quacks gained if you prestige now: ${commas(possible - current)}\n\n` +
      `Next quack progress: \`${progressBar} ${commas(diff)} \`\n\n` +
      'Say \'!prestige me\' to start the prestige process.' +
      `\n\nYour prestige is currently boosting your CPS by ${commas((prestigeMultiplier(user) - 1) * 100)}%`
    )
  }
}//, true, adminOnly)

const prestigeConfirmRoute = async ({ event, say, user, YEET }) => {
  if (YEET) {
    return say(prestigeMenu(user))
  }
  const possible = possiblePrestige(user.coinsAllTime)
  const current = user.prestige
  if (possible <= current) {
    await say('You don\'t have enough HVAC to prestige right now!')
    return
  }
  if (event?.text !== '!!prestige me') {
    await say('Say exactly \'!!prestige me\' to confirm')
    return
  }
  await makeBackup()

  user.isPrestiging = true

  user.quacks ??= 0
  user.quacks += (possible - user.prestige)

  user.prestige = possible
  user.highestEver = 0
  user.coins = 0
  user.items = {}
  user.holdings = {}
  const starterUpgrades = (user.quackUpgrades?.starter || [])
  starterUpgrades.forEach(upgradeName => quackStore[upgradeName].effect(user))
  user.upgrades = {}

  await say(prestigeMenu(user))
  await say(`Say !quack _upgrade-name_ to purchase new quackgrades!`)
  await saveUser(event.user, user, 'prestiging')
  //await say('You prestiged! Check out !quackstore to see what you can buy!')
}

const quackStoreListing = (showCost = true) => ([name, upgrade]) =>
  `:${upgrade.emoji}: *${name}* - ${showCost ? 'Costs' : 'Worth'} *${upgrade.cost} Quack.*\n\n_${upgrade.description}_`

const allUserQuackUpgrades = user =>
  Object.entries(user.quackUpgrades || {})
    .map(([type, upgrades]) => upgrades).flatMap(x => x)

const hasPreReqs = user => ([name, upgrade]) => {
  if (!upgrade.preReqs) {
    return true
  }
  const allUserUpgrades = allUserQuackUpgrades(user)
  return upgrade.preReqs.every(preReq => allUserUpgrades.includes(preReq))
}

const owns = (user, [name, upgrade]) => allUserQuackUpgrades(user).includes(name)

const ownedQuackItems = user => Object.entries(quackStore).filter(upgrade => owns(user, upgrade))

const unownedQuackItems = user => Object.entries(quackStore).filter(upgrade => !owns(user, upgrade))

const quackStoreText = user =>
  unownedQuackItems(user)
    .filter(hasPreReqs(user))
    .map(quackStoreListing(true))
    .join('\n\n') +
  `\n\nYou have ${user.quacks ??= 0} quacks to spend.` +
  `\nQuackStore upgrades are currently boosting your CPS by ${commas((quackGradeMultiplier(user) - 1) * 100)}%`

const quackStoreRoute = async ({ user, say, args, YEET, event }) => {
  user.quackUpgrades ??= {}
  if (!args[0] || !YEET) {
    await say(quackStoreText(user))
    return
  }
  const quackItem = quackStore[args[0]]
  if (!quackItem || !unownedQuackItems(user).find(([name]) => name === args[0])) {
    await say(`'${args[0]}' is not available in the quack store!`)
    return
  }
  const quacks = user.quacks ??= 0
  if (quackItem.cost > quacks) {
    await say(`${args[0]} costs ${quackItem.cost} Quacks, but you only have ${quacks}!`)
    return
  }
  user.quacks -= quackItem.cost
  user.quackUpgrades[quackItem.type] ??= []
  user.quackUpgrades[quackItem.type].push(args[0])
  if (quackItem.type === 'starter') {
    quackItem.effect(user)
  }

  await say(`You bought ${args[0]}!`)
  await saveUser(event.user, user, 'quackgrade purchased')
}

const buyQuackGradeButton = quackgrade => {
  //console.log('buyQuackGradeButton', quackgrade[1])
  const [name, object] = quackgrade
  return {
    type: 'section',
      text: {
    type: 'mrkdwn',
      text: `:${object.emoji}: ${object.name} - ${object.cost} Quacks\n_${object.description}_`
    },
    accessory: {
      type: 'button',
        text: {
        type: 'plain_text',
          text: 'Buy',
          emoji: true
      },
      value: 'click_me_123',
        action_id: `buy-quackgrade-${name}`
    }
  }
}

const prestigeMenu = (user, extraMessage = '') => {
  user.quackUpgrades ??= {}
  const quacks = user.quacks ??= 0
  return {
    text: 'Prestige menu',
    blocks: [
      {
        type: 'section',
        text: {
          type: 'mrkdwn',
          text: `${extraMessage && extraMessage + '\n'}\n_You have ${quacks} quacks to spend._`
          // text: `${extraMessage && extraMessage + '\n'}_*PRESTIGE IN PROGRESS*_\n_You have ${quacks} quacks to spend. You may ONLY spend quacks on this menu._`
        }
      },
      // {
      //   type: 'section',
      //   text: {
      //     type: 'mrkdwn',
      //     text: '~Challenge mode~ _TODO_'
      //   },
      //   accessory: {
      //     type: 'static_select',
      //     placeholder: {
      //       type: 'plain_text',
      //       text: 'No challenge',
      //       emoji: true
      //     },
      //     options: [
      //       {
      //         text: {
      //           type: 'plain_text',
      //           text: 'No challenge',
      //           emoji: true
      //         },
      //         value: 'no-challenge'
      //       },
      //       /*
      //       {
      //         text: {
      //           type: 'plain_text',
      //           text: 'Clean Start (no prestige bonuses)',
      //           emoji: true
      //         },
      //         value: 'clean-start'
      //       }*/
      //     ],
      //     action_id: 'challenge_select-action'
      //   }
      // },
      {
        type: 'section',
        text: {
          type: 'mrkdwn',
          text: '*Available Quackgrades:*'
        }
      },
      ...unownedQuackItems(user).filter(hasPreReqs(user)).map(buyQuackGradeButton),
      // {
      //   type: 'actions',
      //   elements: [
      //     {
      //       type: 'button',
      //       text: {
      //         type: 'plain_text',
      //         text: 'Complete Prestige',
      //         emoji: true
      //       },
      //       value: 'complete_prestige',
      //       action_id: 'complete_prestige'
      //     }
      //   ]
      // }
    ]
  }
}

const buyQuackGrade = async ({ body, ack, say, trueSay, payload }) => {
  await ack()
  const buying = payload.action_id.substring('buy-quackgrade-'.length)

  console.log(`buyQuackGrade ${buying} clicked`)
  const user = await getUser(body.user.id)
  // if (!user.isPrestiging) {
  //   console.log('You must be prestiging!')
  //   return say(`You must be prestiging to use this menu!`)
  // }
  const words = ['', buying, body.actions[0].text]
  const [, ...args] = words

  let extraMessage = ''
  //say = async text => extraMessage = text
  console.log('quackStoreRoute')
  await quackStoreRoute({ say, args, user, YEET: true })

  await slack.app.client.chat.update({
    channel: body.channel.id,
    ts: body.message.ts,
    ...prestigeMenu(user, extraMessage)
  })
}

Object.keys(quackStore).forEach(itemName => slack.app.action('buy-quackgrade-' + itemName, buyQuackGrade))

slack.app.action('complete_prestige', async ({ body, ack, say }) => {
  await ack()

  const user = await getUser(body.user.id)
  delete user.isPrestiging

  await slack.app.client.chat.delete({
    channel: body.channel.id,
    ts: body.message.ts,
  })

  await say(`Prestige complete!`)
  await saveUser(body.user.id, user, 'prestige complete')
})

const prestigeMenuRoute = async ({ say, user }) => {
  user.quackUpgrades ??= {}
  user.quacks ??= 0
  await say(prestigeMenu(user))
}

const ownedQuacksText = user =>
  ownedQuackItems(user)
    .filter(hasPreReqs(user))
    .map(quackStoreListing(false))
    .join('\n\n') +
  `\n\nQuackStore upgrades are currently boosting your CPS by ${commas((quackGradeMultiplier(user) - 1) * 100)}%`

const ownedQuacksRoute = async ({ say, user }) => {
  user.quackUpgrades ??= {}
  user.quacks ??= 0
  await say(ownedQuacksText(user))
}

module.exports = {
  quackStoreRoute,
  prestigeRoute,
  prestigeConfirmRoute,
  prestigeMenuRoute,
  ownedQuacksRoute
}
