import { captureException } from '@sentry/react'
import {
  FluidSlugType,
  FluidState,
  FluidType,
  KonnectorUpdate,
  Season,
} from 'enums'
import get from 'lodash/get'
import { DateTime, Interval } from 'luxon'
import { FluidStatus, GetRelationshipsReturn, Relation } from 'models'
import challengeData from '../db/challengeEntity.json'

export function getFluidType(type: string) {
  switch (type.toUpperCase()) {
    case 'ELECTRICITY':
      return FluidType.ELECTRICITY
    case 'WATER':
      return FluidType.WATER
    case 'GAS':
      return FluidType.GAS
    default:
      return FluidType.ELECTRICITY
  }
}
export function getKonnectorSlug(fluidType: FluidType) {
  switch (fluidType) {
    case FluidType.ELECTRICITY:
      return FluidSlugType.ELECTRICITY
    case FluidType.WATER:
      return FluidSlugType.WATER
    case FluidType.GAS:
      return FluidSlugType.GAS
    default:
      throw new Error('unknown fluidtype')
  }
}
/** Return lowercase fluidtype
 * @example FluidType.ELECTRICITY => 'electricity'
 */
export function getFluidName(fluidType: FluidType) {
  return FluidType[fluidType].toLowerCase()
}

export function getKonnectorUpdateError(type: string) {
  switch (type.toUpperCase()) {
    case 'USER_ACTION_NEEDED.OAUTH_OUTDATED':
      return KonnectorUpdate.ERROR_UPDATE_OAUTH
    case 'LOGIN_FAILED':
      return KonnectorUpdate.LOGIN_FAILED
    case 'CHALLENGE_ASKED':
      return KonnectorUpdate.ERROR_CONSENT_FORM_GAS
    default:
      return KonnectorUpdate.ERROR_UPDATE
  }
}
export function isKonnectorActive(
  fluidStatus: FluidStatus[],
  fluidType: FluidType
): boolean {
  if (fluidType === FluidType.MULTIFLUID) {
    if (
      fluidStatus.filter(
        fluid =>
          fluid.status === FluidState.NOT_CONNECTED ||
          fluid.status === FluidState.KONNECTOR_NOT_FOUND
      ).length === 3
    ) {
      return false
    } else {
      return true
    }
  }
  if (
    fluidStatus[fluidType].status === FluidState.NOT_CONNECTED ||
    fluidStatus[fluidType].status === FluidState.KONNECTOR_NOT_FOUND
  ) {
    return false
  } else return true
}
export function formatNumberValues(
  value: number | null,
  fluidStyle?: string,
  toBeCompared = false
) {
  if (value || value === 0) {
    const localeValue = value.toLocaleString('fr-FR', {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    })
    const noSpaceValue = parseInt(localeValue.replace(/\s/g, ''))
    if (toBeCompared) return noSpaceValue
    if (fluidStyle && noSpaceValue >= 1000) {
      const convertedValue = (noSpaceValue / 1000).toFixed(2).replace('.', ',')
      return convertedValue
    } else return localeValue
  } else {
    return '--,--'
  }
}

/**
 * Get one relation in doc
 * @param {object} doc - DocumentEntity
 * @param {string} relName - Name of the relation
 */
export function getRelationship<D>(doc: D, relName: string): Relation {
  return get(doc, `relationships.${relName}.data`, [])
}

/**
 * Get array of items in one relation in doc
 * @param {object} doc - DocumentEntity
 * @param {string} relName - Name of the relation
 */
export function getRelationshipHasMany<D>(doc: D, relName: string): Relation[] {
  return get(doc, `relationships.${relName}.data`, [])
}

/**
 * Get many relations in doc
 * @param {object} doc - DocumentEntity
 * @param {Array<[relName: string]: Array<Relation>>} relNameList - Array of name of the relations
 */
export function getRelationships<D>(
  doc: D,
  relNameList: Array<string>
): GetRelationshipsReturn {
  return relNameList.map(relName => ({
    [relName]: get(doc, `relationships.${relName}.data`, []),
  }))[0]
}

/**
 * Import a svg file with format : id.svg
 * @param id
 * @param pathType
 */
export const importIconById = async (
  id: string,
  pathType: string
): Promise<string | undefined> => {
  let importedChallengeIcon
  try {
    importedChallengeIcon = await import(
      /* webpackMode: "eager" */ `assets/icons/visu/${pathType}/${id}.svg`
    )
    if (importedChallengeIcon) {
      return importedChallengeIcon.default
    }
  } catch (e) {
    console.error(`Could not import icon ${pathType}/${id}`)
    captureException(e)
  }
}

export const getMonthFullName = (month: number) => {
  const monthNames = [
    'Janvier',
    'Février',
    'Mars',
    'Avril',
    'Mai',
    'Juin',
    'Juillet',
    'Août',
    'Septembre',
    'Octobre',
    'Novembre',
    'Décembre',
  ] as const
  if (month < 1 || month > 12) throw new Error('Invalid month')
  return monthNames[month - 1]
}

/**
 * Return month string according to month index
 * @Note Equivalent to date.monthLong
 * @param date - DateTime
 * @returns month in french
 */
export const getMonthName = (date: DateTime) => {
  const monthNames = [
    'janvier',
    'février',
    'mars',
    'avril',
    'mai',
    'juin',
    'juillet',
    'août',
    'septembre',
    'octobre',
    'novembre',
    'décembre',
  ] as const
  return monthNames[date.month - 1]
}

/**
 * Return month string according to month index
 * @param date - DateTime
 * @returns "de" month in french
 */
export const getMonthNameWithPrep = (date: DateTime) => {
  const monthNames = [
    'de janvier',
    'de février',
    'de mars',
    `d’avril`,
    'de mai',
    'de juin',
    'de juillet',
    `d’août`,
    'de septembre',
    `d’octobre`,
    'de novembre',
    'de décembre',
  ] as const
  return monthNames[date.month - 1]
}

/**
 * Return season according to following rules
 * - Winter is : 1/11/XXXX => 1/3/XXXX
 * - Summer is : 1/6/XXXX => 1/9/XXXX
 * @returns Season
 */
export const getSeason = (): Season => {
  const currentDate: DateTime = DateTime.local().setZone('utc', {
    keepLocalTime: true,
  })
  const currentYear: number = currentDate.year
  const winterStart: DateTime = DateTime.local(currentYear, 11, 1).setZone(
    'utc',
    {
      keepLocalTime: true,
    }
  )
  const winterEnd: DateTime = DateTime.local(currentYear + 1, 3, 1).setZone(
    'utc',
    {
      keepLocalTime: true,
    }
  )

  const summerStart: DateTime = DateTime.local(currentYear, 6, 1).setZone(
    'utc',
    {
      keepLocalTime: true,
    }
  )
  const summerEnd: DateTime = DateTime.local(currentYear, 9, 1).setZone('utc', {
    keepLocalTime: true,
  })
  const summerInterval: Interval = Interval.fromDateTimes(
    summerStart,
    summerEnd
  )
  const winterInterval: Interval = Interval.fromDateTimes(
    winterStart,
    winterEnd
  )

  if (summerInterval.contains(currentDate)) {
    return Season.SUMMER
  } else if (winterInterval.contains(currentDate)) {
    return Season.WINTER
  } else {
    return Season.NONE
  }
}

/**
 *  Returns the challenge title with line return ( \n ). The result is coming from challengeEntity.json
 * @param userChallengeId EXPLORATION001
 * @returns Simone\nVEILLE
 */
export const getChallengeTitleWithLineReturn = (userChallengeId: string) => {
  for (const challenge of challengeData) {
    if (challenge._id === userChallengeId) {
      return challenge.title_line_return
    }
  }
}

/**
 * Returns today's date, example: 2022-09-28T00:00:00.000Z
 * @returns DateTime
 */
export const getTodayDate = () =>
  DateTime.local()
    .setZone('utc', {
      keepLocalTime: true,
    })
    .startOf('day')