import { FluidType } from 'enums'
import fs from 'fs'
import { DateTime } from 'luxon'
import { DataloadEntity } from 'models'
import config from './config'
const fluidConfig = require('../src/constants/config.json').fluidConfig

/*
 * Create dummy data files for each fluid.
 * Hourly data is not generated
 */

type IMockData = Omit<DataloadEntity, 'id'>

/** Generate a random float between min and max */
function getRandomNumber(min: number, max: number) {
  let randomFloat = Math.random() * (max - min) + min
  // Round to two decimal places
  randomFloat = Math.round(randomFloat * 100) / 100
  return randomFloat
}

const generateHalfAnHourData = (
  startingDate: DateTime,
  endingDate: DateTime,
  min: number,
  max: number
) => {
  let parsingDate = DateTime.local(
    startingDate.year,
    startingDate.month,
    startingDate.day,
    0,
    0
  )
  const halfAnHourDumpArray: IMockData[] = []
  while (parsingDate <= endingDate) {
    const load = getRandomNumber(min, max)
    halfAnHourDumpArray.push({
      load: load,
      year: parsingDate.year,
      month: parsingDate.month,
      day: parsingDate.day,
      hour: parsingDate.hour,
      minute: parsingDate.minute,
      price: load * fluidConfig[0].coefficient,
    })
    parsingDate = parsingDate.plus({ minute: 30 })
  }
  return halfAnHourDumpArray
}

const generateData = (
  startingDate: DateTime,
  endingDate: DateTime,
  min: number,
  max: number,
  fluidType: FluidType
) => {
  let parsingDate = DateTime.local(
    startingDate.year,
    startingDate.month,
    startingDate.day
  )
  const dayDumpArray: IMockData[] = []
  while (parsingDate <= endingDate) {
    const load = getRandomNumber(min, max)
    dayDumpArray.push({
      load: load,
      year: parsingDate.year,
      month: parsingDate.month,
      day: parsingDate.day,
      hour: 0,
      minute: 0,
      price: load * fluidConfig[fluidType].coefficient,
    })
    parsingDate = parsingDate.plus({ days: 1 })
  }
  return dayDumpArray
}

/** Function to aggregate load data for a specific period */
function aggregateLoadData(data: IMockData[], period: string) {
  const aggregatedData: Record<string, IMockData> = {}
  data.forEach(entry => {
    let key = ''
    const entryCopy = { ...entry }
    switch (period) {
      case 'day':
        key = `${entryCopy.year}-${entryCopy.month}-${entryCopy.day}`
        entryCopy.hour = 0
        entryCopy.minute = 0
        break
      case 'month':
        key = `${entryCopy.year}-${entryCopy.month}`
        entryCopy.day = 0
        entryCopy.minute = 0
        break
      case 'year':
        key = `${entryCopy.year}`
        entryCopy.month = 0
        entryCopy.day = 0
        entryCopy.minute = 0
        break
      default:
        break
    }
    if (!aggregatedData[key]) {
      aggregatedData[key] = {
        load: entryCopy.load,
        year: entryCopy.year,
        month: entryCopy.month,
        day: entryCopy.day,
        hour: entryCopy.hour,
        minute: entryCopy.minute,
        price: entryCopy.price,
      }
    } else {
      aggregatedData[key].load += entryCopy.load
      if (aggregatedData[key].price !== undefined) {
        aggregatedData[key].price = 0
      }
    }
  })

  return Object.values(aggregatedData)
}

// Create data folder
const dir = './data'
if (!fs.existsSync(dir)) {
  console.log('Create data folder...')
  fs.mkdirSync(dir)
}

const startingDate = config.startingDate
const endingDate = config.endingDate
const halfHourStartingDate = config.halfHourStartingDate

const elecHalfHourData = generateHalfAnHourData(
  halfHourStartingDate,
  endingDate.endOf('day'),
  0.12,
  0.36
)
// Aggregate all half-hour data available and generate more daily data between startingDate and halfHourStartingDate
const elecAggregatedDayData = aggregateLoadData(elecHalfHourData, 'day')
const elecGeneratedDayData = generateData(
  startingDate,
  halfHourStartingDate.minus({ days: 1 }),
  4,
  8,
  0
)
const elecDayData = [...elecAggregatedDayData, ...elecGeneratedDayData]
const elecMonthData = aggregateLoadData(elecDayData, 'month')
const elecYearData = aggregateLoadData(elecMonthData, 'year')

const gasDayData = generateData(startingDate, endingDate, 16, 68, 2)
const gasMonthData = aggregateLoadData(gasDayData, 'month')
const gasYearData = aggregateLoadData(gasMonthData, 'year')

const waterDayData = generateData(startingDate, endingDate, 200, 300, 1)
const waterMonthData = aggregateLoadData(waterDayData, 'month')
const waterYearData = aggregateLoadData(waterMonthData, 'year')

const dump = {
  'com.grandlyon.enedis.minute': elecHalfHourData,
  'com.grandlyon.enedis.day': elecDayData,
  'com.grandlyon.enedis.month': elecMonthData,
  'com.grandlyon.enedis.year': elecYearData,

  'com.grandlyon.grdf.day': gasDayData,
  'com.grandlyon.grdf.month': gasMonthData,
  'com.grandlyon.grdf.year': gasYearData,

  'com.grandlyon.egl.day': waterDayData,
  'com.grandlyon.egl.month': waterMonthData,
  'com.grandlyon.egl.year': waterYearData,
}

const dumpString = JSON.stringify(dump)

fs.writeFile('data/loads.json', dumpString, function (err: unknown) {
  if (err) console.log('error', err)
})