package mqe

import (
	"fmt"
)

func getPeriodDateTime(groupBy GroupBy, lastDayOfMonth int, firstHourOfDay int) (dt string, err error) {
	//fmt.Printf("getPeriodDateTime: %s, lastDay: %d, firstHour: %d\n", groupBy, lastDayOfMonth, firstHourOfDay)
	// Если FirstHourOfDay и LastDayOfMonth равны 0 - модифицировать дату не нужно
	dt = `FROM_UNIXTIME(tm)`

	switch groupBy {
	case ByDay:
		if firstHourOfDay > 0 {
			dt = fmt.Sprintf(`
			IF (HOUR(FROM_UNIXTIME(tm)) >= %d, 
				FROM_UNIXTIME(tm), 
				DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY)
			)`,
				firstHourOfDay)
		}

	case ByMonth:
		if lastDayOfMonth > 0 {
			if lastDayOfMonth > 28 {
				// На всякий случай добавляем защиту от дурака, ибо модификация даты
				// в запросе (+1 месяц) для 29, 30 и 31 чисел сделает запрос неверным.
				err = fmt.Errorf("LastDayOfMonth: %d, max allowed value is 28", lastDayOfMonth)
				return
			}

			if firstHourOfDay > 0 {
				// В псевдокоде модификация времени показания по корректный период
				// выглядит так:
				//
				// if hour >= FirstHourOfDay {
				// 	  if day <= LastDayOfMonth {
				// 		  return tm
				// 	  } else {
				// 		  return tm + 1 month
				// 	  }
				// } else {
				// 	  if (day - 1) <= LastDayOfMonth {
				// 		  return tm - 1 day
				// 	  } else {
				// 		  return tm - 1 day + 1 month
				// 	  }
				// }
				dt = fmt.Sprintf(`
				IF (HOUR(FROM_UNIXTIME(tm)) >= %d, 
					IF (DAYOFMONTH(FROM_UNIXTIME(tm)) <= %d, 
						FROM_UNIXTIME(tm), 
						DATE_ADD(FROM_UNIXTIME(tm), INTERVAL 1 MONTH)
					),
					IF (DAYOFMONTH(DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY)) <= %d, 
						DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY), 
						DATE_ADD(DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY), INTERVAL 1 MONTH)
					)
				)`,
					firstHourOfDay, lastDayOfMonth, lastDayOfMonth)
			} else {
				dt = fmt.Sprintf(`
				IF (DAYOFMONTH(FROM_UNIXTIME(tm)) <= %d, 
					FROM_UNIXTIME(tm), 
					DATE_ADD(FROM_UNIXTIME(tm), INTERVAL 1 MONTH)
				)`,
					lastDayOfMonth)
			}
		} else {
			if firstHourOfDay > 0 {
				dt = fmt.Sprintf(`
				IF (HOUR(FROM_UNIXTIME(tm)) >= %d, 
					FROM_UNIXTIME(tm), 
					DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY)
				)`,
					firstHourOfDay)
			}
		}
	}
	return
}

func getDateTimeFacingFHD(firstHourOfDay int) (dt string, err error) {
	if firstHourOfDay > 0 {
		dt = fmt.Sprintf(`
		IF (HOUR(FROM_UNIXTIME(tm)) >= %d, 
			FROM_UNIXTIME(tm), 
			DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY)
		)`,
			firstHourOfDay)
	} else {
		// Если FirstHourOfDay = 0 - модифицировать дату не нужно
		dt = "FROM_UNIXTIME(tm)"
	}
	return
}

func getDateTimeFacingFHDAndLDM(firstHourOfDay int, lastDayOfMonth int) (dt string, err error) {
	// Если FirstHourOfDay и LastDayOfMonth равны 0 - модифицировать дату не нужно
	dt = "FROM_UNIXTIME(tm)"

	if lastDayOfMonth > 0 {
		if lastDayOfMonth > 28 {
			// На всякий случай добавляем защиту от дурака, ибо модификация даты
			// в запросе (+1 месяц) для 29, 30 и 31 чисел сделает запрос неверным.
			err = fmt.Errorf("LastDayOfMonth: %d, max allowed value is 28", lastDayOfMonth)
			return
		}

		if firstHourOfDay > 0 {
			// В псевдокоде модификация времени показания по корректный период
			// выглядит так:
			//
			// if hour >= FirstHourOfDay {
			// 	  if day <= LastDayOfMonth {
			// 		  return tm
			// 	  } else {
			// 		  return tm + 1 month
			// 	  }
			// } else {
			// 	  if (day - 1) <= LastDayOfMonth {
			// 		  return tm - 1 day
			// 	  } else {
			// 		  return tm - 1 day + 1 month
			// 	  }
			// }
			dt = fmt.Sprintf(`
			IF (HOUR(FROM_UNIXTIME(tm)) >= %d, 
				IF (DAYOFMONTH(FROM_UNIXTIME(tm)) <= %d, 
					FROM_UNIXTIME(tm), 
					DATE_ADD(FROM_UNIXTIME(tm), INTERVAL 1 MONTH)
				),
				IF (DAYOFMONTH(DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY)) <= %d, 
					DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY), 
					DATE_ADD(DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY), INTERVAL 1 MONTH)
				)
			)`,
				firstHourOfDay, lastDayOfMonth, lastDayOfMonth)
		} else {
			dt = fmt.Sprintf(`
			IF (DAYOFMONTH(FROM_UNIXTIME(tm)) <= %d, 
				FROM_UNIXTIME(tm), 
				DATE_ADD(FROM_UNIXTIME(tm), INTERVAL 1 MONTH)
			)`,
				lastDayOfMonth)
		}
	} else {
		if firstHourOfDay > 0 {
			dt = fmt.Sprintf(`
			IF (HOUR(FROM_UNIXTIME(tm)) >= %d, 
				FROM_UNIXTIME(tm), 
				DATE_SUB(FROM_UNIXTIME(tm), INTERVAL 1 DAY)
			)`,
				firstHourOfDay)
		}
	}
	return
}
