'use strict'

/*******************************************************************************
Import finalized monthly DBRs.
*******************************************************************************/

var util = require('util')

var log = require('loglevel')
var rollbar = require('rollbar')
var moment = require('moment')

var BaseParser = require('./lib/baseparser.js')
var DBR = require('./lib/dbr.js')
var Redshift = require('./lib/redshift.js')
var cliUtils = require('./lib/cliutils.js')

rollbar.init(process.env.ROLLBAR_TOKEN, {environment: process.env.ROLLBAR_ENVIRONMENT})
rollbar.handleUncaughtExceptions(process.env.ROLLBAR_TOKEN,
                                 {exitOnUncaughtException: true})

var parser = new BaseParser({
  version: '0.0.1',
  addHelp: true,
  description: 'Imports finalized (whole-month) detailed billing reports'
})

parser.addArgument(
  ['--force'], {
    action: 'storeConst',
    dest: 'force',
    help: 'Ignore and overwrite an existing staged DBR.',
    constant: true
  }
)

parser.addArgument(
  ['--specific'], {
    help: "Import a specific month's DBR. Specified in YYYY-MM format."
  }
)

var args = parser.parseArgs()

if (args.debug) {
  log.setLevel('debug')
  log.debug('Debugging output enabled.')
} else {
  log.setLevel('info')
}
log.debug(`Resolved invocation arguments were:\n${util.inspect(args)}`)

// Instantiate a DBR object to work with.
var dbrClientOptions = {
  accessKeyId: args.source_key,
  secretAccessKey: args.source_secret
}

var stagingClientOptions = {
  accessKeyId: args.staging_key,
  secretAccessKey: args.staging_secret
}

var dbr = new DBR(dbrClientOptions, stagingClientOptions,
                  args.source_bucket, args.staging_bucket)

// Instantiate a Redshift object to work with.
var redshift = new Redshift(args.redshift_uri, {
      key: args.staging_key,
      secret: args.staging_secret
})

let startTime = moment.utc()

chooseDBR()
  .then(importDBRCheck)
  .then(stageDBRCheck)
  .then(importDBR)
  .then(vacuum)
  .then(function () {
    cliUtils.runCompleteHandler(startTime, 0)
  })
  .catch(cliUtils.rejectHandler)

function chooseDBR () {
  return new Promise(function (resolve, reject) {
    if (args.specific) {
      try {
        let match = /^(\d{4})-(\d{2})$/.exec(args.specific)
        if (match === null) {
          return reject('--specific requires a year and month parameter in the form of YYYY-MM')
        }
        let month = moment.utc([match[1], match[2]])
        return resolve(dbr.findDBR(month))
      } catch (err) {
        return reject(err)
      }
    } else {
      return resolve(dbr.getLatestFinalizedDBR())
    }
  })
}

// Given a latest finalized DBR object, decide whether to import it
function importDBRCheck (finalizedDBR) {
  return redshift.hasMonth(finalizedDBR.Month).then(function (hasMonth) {
    if (hasMonth) {
      log.info(`No new DBRs to import.`)
      cliUtils.runCompleteHandler(startTime, 0)
    } else {
      return finalizedDBR
    }
  })
}

// Given a DBR, (optionally) stage it
function stageDBRCheck (finalizedDBR) {
  return dbr.findStagedDBR(finalizedDBR.Month).then(
    function (stagedDBR) {
      let dbrMonth = stagedDBR.Month.format('MMMM YYYY')
      // DBR is staged!
      if (!args.force) {
        // No need to re-stage
        log.warn(`Using existing staged DBR for ${dbrMonth}.`)
        let s3uri = `s3://${args.staging_bucket}/${stagedDBR.Key}`
        log.debug(`Staged s3uri: ${s3uri}`)
        return ({s3uri: s3uri, month: stagedDBR.Month})
      } else {
        // Force re-stage
        log.warn(`--force specified, overwriting staged DBR for ${dbrMonth}`)
        return dbr.stageDBR(stagedDBR.Month).then(function (s3uri) {
          return ({s3uri: s3uri, month: stagedDBR.Month})
        })
      }
    },
    function (err) {
      // DBR not staged. Stage then import.
      log.debug(`DBR not staged: ${err}`)
      log.info(`Staging DBR for ${finalizedDBR.Month.format('MMMM YYYY')}.`)
      return dbr.stageDBR(finalizedDBR.Month).then(function (s3uri) {
        return ({s3uri: s3uri, month: finalizedDBR.Month})
      })
    }
  )
}

// Given an object like {s3uri: <uri>, month: <moment>}
// Execute the import.
function importDBR (params) {
  log.info(`Importing DBR for ${params.month.format('MMMM YYYY')}`)
  return redshift.importFullMonth(params.s3uri, params.month)
}

// Run VACUUM on the line_items table
function vacuum () {
  if (!args.no_vacuum) {
    log.info('Running VACUUM on line_items...')
    return redshift.vacuum(process.env.LINE_ITEMS_TABLE_NAME || 'line_items')
  } else {
    log.info('--no-vacuum specified, skiping vacuum.')
    return
  }
}

@@ -2212,24 +2212,85 @@
 specific) %7B%0A
+      log.debug(%60Invoked with --specific $%7Bargs.specific%7D.%60)%0A
       try %7B%0A
@@ -2289,16 +2289,16 @@
   try %7B%0A
-
         
@@ -2498,51 +2498,173 @@
     
-let month = moment.utc(%5Bmatch%5B1%5D, match%5B2%5D%5D
+// moment.utc month argument is zero-indexed%0A        let month = moment.utc(%5Bmatch%5B1%5D, match%5B2%5D - 1%5D)%0A        log.debug(%60Attempting to import $%7Bmonth.toISOString()%7D%60
 )%0A  
@@ -2757,24 +2757,24 @@
 rr)%0A      %7D%0A
-
     %7D else %7B
@@ -2766,32 +2766,113 @@
  %7D%0A    %7D else %7B%0A
+      log.debug(%60Invoked without --specific. Targeting latest finalized DBR...%60)%0A
       return res

Fix off-by-one in --specific date handling