import { timeUnitForRange, whenRange } from '@/lib/time'

export function withClause (range) {
  const unit = timeUnitForRange(range)

  return `
    WITH range_values AS (
      SELECT date_trunc('${unit}', $1) as minval,
             date_trunc('${unit}', $2) as maxval
    ),
    times AS (
      SELECT generate_series(minval, maxval, interval '1 ${unit}') as time
      FROM range_values
    )
  `
}

export function intervalClause (range, table) {
  const unit = timeUnitForRange(range)

  return `date_trunc('${unit}', "${table}".created_at)  >= date_trunc('${unit}', $1) AND date_trunc('${unit}', "${table}".created_at) <= date_trunc('${unit}', $2) `
}

export function viewIntervalClause (range, view) {
  const unit = timeUnitForRange(range)
  return `"${view}".t >= date_trunc('${unit}', timezone('America/Chicago', $1)) AND date_trunc('${unit}', "${view}".t) <= date_trunc('${unit}', timezone('America/Chicago', $2)) `
}

export function viewGroup (range, view) {
  const unit = timeUnitForRange(range)
  return `(
    (SELECT *
      FROM ${view}_days
      WHERE ${viewIntervalClause(range, `${view}_days`)})
    UNION ALL
    (SELECT *
      FROM ${view}_hours
      WHERE ${viewIntervalClause(range, `${view}_hours`)}
      ${unit === 'hour' ? '' : `AND "${view}_hours".t >= date_trunc('day', timezone('America/Chicago', now()))`})
    UNION ALL
    (SELECT * FROM
      ${view}(
      date_trunc('hour', timezone('America/Chicago', now())),
      date_trunc('hour', timezone('America/Chicago', now())), '1 hour'::INTERVAL, 'hour')
      WHERE "${view}".t >= date_trunc('${unit}', timezone('America/Chicago', $1))
      AND "${view}".t <= date_trunc('${unit}', timezone('America/Chicago', $2)))
  ) u`
}

export default {
  Query: {
    registrationGrowth: async (parent, { when, from, to }, { models }) => {
      const range = whenRange(when, from, to)

      return await models.$queryRawUnsafe(`
        SELECT date_trunc('${timeUnitForRange(range)}', t) at time zone 'America/Chicago' as time, json_build_array(
          json_build_object('name', 'referrals', 'value', sum(referrals)),
          json_build_object('name', 'organic', 'value', sum(organic))
        ) AS data
        FROM ${viewGroup(range, 'reg_growth')}
        GROUP BY time
        ORDER BY time ASC`, ...range)
    },
    spenderGrowth: async (parent, { when, to, from }, { models }) => {
      const range = whenRange(when, from, to)

      return await models.$queryRawUnsafe(`
        SELECT date_trunc('${timeUnitForRange(range)}', t) at time zone 'America/Chicago' as time, json_build_array(
          json_build_object('name', 'any', 'value', COUNT(DISTINCT "userId")),
          json_build_object('name', 'jobs', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'STREAM')),
          json_build_object('name', 'boost', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'BOOST')),
          json_build_object('name', 'fees', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'FEE')),
          json_build_object('name', 'poll', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'POLL')),
          json_build_object('name', 'downzaps', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'DONT_LIKE_THIS')),
          json_build_object('name', 'zaps', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'TIP')),
          json_build_object('name', 'donation', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'DONATION')),
          json_build_object('name', 'territories', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'TERRITORY'))
        ) AS data
        FROM ${viewGroup(range, 'spender_growth')}
        GROUP BY time
        ORDER BY time ASC`, ...range)
    },
    itemGrowth: async (parent, { when, to, from }, { models }) => {
      const range = whenRange(when, from, to)

      return await models.$queryRawUnsafe(`
        SELECT date_trunc('${timeUnitForRange(range)}', t) at time zone 'America/Chicago' as time, json_build_array(
          json_build_object('name', 'posts', 'value', sum(posts)),
          json_build_object('name', 'comments', 'value', sum(comments)),
          json_build_object('name', 'jobs', 'value', sum(jobs)),
          json_build_object('name', 'zaps', 'value', sum(zaps)),
          json_build_object('name', 'territories', 'value', sum(territories)),
          json_build_object('name', 'comments/posts', 'value', ROUND(sum(comments)/GREATEST(sum(posts), 1), 2))
        ) AS data
        FROM ${viewGroup(range, 'item_growth')}
        GROUP BY time
        ORDER BY time ASC`, ...range)
    },
    spendingGrowth: async (parent, { when, to, from }, { models }) => {
      const range = whenRange(when, from, to)

      return await models.$queryRawUnsafe(`
        SELECT date_trunc('${timeUnitForRange(range)}', t) at time zone 'America/Chicago' as time, json_build_array(
          json_build_object('name', 'jobs', 'value', sum(jobs)),
          json_build_object('name', 'boost', 'value', sum(boost)),
          json_build_object('name', 'fees', 'value', sum(fees)),
          json_build_object('name', 'zaps', 'value', sum(tips)),
          json_build_object('name', 'donations', 'value', sum(donations)),
          json_build_object('name', 'territories', 'value', sum(territories))
        ) AS data
        FROM ${viewGroup(range, 'spending_growth')}
        GROUP BY time
        ORDER BY time ASC`, ...range)
    },
    stackerGrowth: async (parent, { when, to, from }, { models }) => {
      const range = whenRange(when, from, to)

      return await models.$queryRawUnsafe(`
        SELECT date_trunc('${timeUnitForRange(range)}', t) at time zone 'America/Chicago' as time, json_build_array(
          json_build_object('name', 'any', 'value', COUNT(DISTINCT "userId")),
          json_build_object('name', 'posts', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'POST')),
          json_build_object('name', 'comments', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'COMMENT')),
          json_build_object('name', 'rewards', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'EARN')),
          json_build_object('name', 'referrals', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'REFERRAL')),
          json_build_object('name', 'territories', 'value', COUNT(DISTINCT "userId") FILTER (WHERE type = 'REVENUE'))
        ) AS data
        FROM ${viewGroup(range, 'stackers_growth')}
        GROUP BY time
        ORDER BY time ASC`, ...range)
    },
    stackingGrowth: async (parent, { when, to, from }, { models }) => {
      const range = whenRange(when, from, to)

      return await models.$queryRawUnsafe(`
        SELECT date_trunc('${timeUnitForRange(range)}', t) at time zone 'America/Chicago' as time, json_build_array(
          json_build_object('name', 'rewards', 'value', sum(rewards)),
          json_build_object('name', 'posts', 'value', sum(posts)),
          json_build_object('name', 'comments', 'value', sum(comments)),
          json_build_object('name', 'referrals', 'value', sum(referrals)),
          json_build_object('name', 'territories', 'value', sum(territories))
        ) AS data
        FROM ${viewGroup(range, 'stacking_growth')}
        GROUP BY time
        ORDER BY time ASC`, ...range)
    }
  }
}