import {
  FluidSlugType,
  FluidState,
  FluidType,
  KonnectorUpdate,
  Season,
} from 'enums'
import { DateTime } from 'luxon'
import { FluidStatus } from 'models'
import {
  formatListWithAnd,
  formatNumberValues,
  getChallengeTitleWithLineReturn,
  getFluidName,
  getFluidType,
  getKonnectorSlug,
  getKonnectorUpdateError,
  getMonthFullName,
  getMonthName,
  getMonthNameWithPrep,
  getSeason,
  isKonnectorActive,
} from './utils'

describe('utils test', () => {
  describe('getFluidType test', () => {
    it('should the electricity fluid type', () => {
      const result = getFluidType('eLectRicity')
      expect(result).toBe(FluidType.ELECTRICITY)
    })

    it('should the water fluid type', () => {
      const result = getFluidType('WatER')
      expect(result).toBe(FluidType.WATER)
    })

    it('should the gas fluid type', () => {
      const result = getFluidType('gas')
      expect(result).toBe(FluidType.GAS)
    })
  })
  describe('getKonnectorSlug', () => {
    it('should return correct slug for elec', () => {
      const slug = getKonnectorSlug(FluidType.ELECTRICITY)
      expect(slug).toBe(FluidSlugType.ELECTRICITY)
    })
    it('should return correct slug for water', () => {
      const slug = getKonnectorSlug(FluidType.WATER)
      expect(slug).toBe(FluidSlugType.WATER)
    })
    it('should return correct slug for gas', () => {
      const slug = getKonnectorSlug(FluidType.GAS)
      expect(slug).toBe(FluidSlugType.GAS)
    })
  })
  describe('getKonnectorUpdateError', () => {
    it('should return KonnectorUpdate.ERROR_UPDATE_OAUTH for USER_ACTION_NEEDED.OAUTH_OUTDATED', () => {
      const result = getKonnectorUpdateError(
        'USER_ACTION_NEEDED.OAUTH_OUTDATED'
      )
      expect(result).toBe(KonnectorUpdate.ERROR_UPDATE_OAUTH)
    })
    it('should return KonnectorUpdate.LOGIN_FAILED for LOGIN_FAILED', () => {
      const result = getKonnectorUpdateError('LOGIN_FAILED')
      expect(result).toBe(KonnectorUpdate.LOGIN_FAILED)
    })
    it('should return KonnectorUpdate.ERROR_CONSENT_FORM_GAS for CHALLENGE_ASKED', () => {
      const result = getKonnectorUpdateError('CHALLENGE_ASKED')
      expect(result).toBe(KonnectorUpdate.ERROR_CONSENT_FORM_GAS)
    })
    it('should return KonnectorUpdate.ERROR_UPDATE for an unknown type', () => {
      const result = getKonnectorUpdateError('UNKNOWN_TYPE')
      expect(result).toBe(KonnectorUpdate.ERROR_UPDATE)
    })
  })

  describe('isKonnectorActive', () => {
    describe('for MULTIFLUID', () => {
      it('should return false when all fluids are not connected', () => {
        const fluidStatus = [
          { status: FluidState.NOT_CONNECTED },
          { status: FluidState.KONNECTOR_NOT_FOUND },
          { status: FluidState.NOT_CONNECTED },
        ] as FluidStatus[]
        const result = isKonnectorActive(fluidStatus, FluidType.MULTIFLUID)
        expect(result).toBe(false)
      })
      it('should return true when some fluids are connected', () => {
        const fluidStatus = [
          { status: FluidState.DONE },
          { status: FluidState.NOT_CONNECTED },
          { status: FluidState.DONE },
        ] as FluidStatus[]
        const result = isKonnectorActive(fluidStatus, FluidType.MULTIFLUID)
        expect(result).toBe(true)
      })
    })

    describe('for SINGLE fluids', () => {
      it('should return false for a single fluid not connected', () => {
        const fluidStatus = [
          {},
          {
            status: FluidState.NOT_CONNECTED,
            fluidType: FluidType.GAS,
          },
          {
            status: FluidState.KONNECTOR_NOT_FOUND,
            fluidType: FluidType.WATER,
          },
        ] as FluidStatus[]
        expect(isKonnectorActive(fluidStatus, FluidType.GAS)).toBe(false)
        expect(isKonnectorActive(fluidStatus, FluidType.WATER)).toBe(false)
      })
      it('should return true for a single fluid connected', () => {
        const fluidStatus = [
          {
            status: FluidState.DONE,
            fluidType: FluidType.ELECTRICITY,
          },
          { status: FluidState.ERROR, fluidType: FluidType.WATER },
          { status: FluidState.ERROR_LOGIN_FAILED, fluidType: FluidType.GAS },
        ] as FluidStatus[]
        expect(isKonnectorActive(fluidStatus, FluidType.ELECTRICITY)).toBe(true)
        expect(isKonnectorActive(fluidStatus, FluidType.GAS)).toBe(true)
        expect(isKonnectorActive(fluidStatus, FluidType.WATER)).toBe(true)
      })
    })
  })

  describe('formatNumberValues test', () => {
    it('should return --,-- if there is not value', () => {
      const result = formatNumberValues(null)
      expect(result).toBe('--,--')
    })

    it('should return a value at english number format two digits decimal', () => {
      const result = formatNumberValues(2000.555)
      expect(result).toEqual('2 000,56')
    })

    it('should return a float value', () => {
      const result = formatNumberValues(2000.55, '', true)
      expect(result).toEqual(2000)
    })
  })

  describe('getSeason test', () => {
    it('should return summer', () => {
      const now = DateTime.local().setZone('utc', {
        keepLocalTime: true,
      })
      jest
        .spyOn(DateTime, 'local')
        .mockReturnValueOnce(now.set({ day: 12, month: 6, year: 2021 }))
      const result = getSeason()
      expect(result).toBe(Season.SUMMER)
    })

    it('should return winter', () => {
      const now = DateTime.local().setZone('utc', {
        keepLocalTime: true,
      })
      jest
        .spyOn(DateTime, 'local')
        .mockReturnValueOnce(now.set({ day: 1, month: 12, year: 2021 }))
      const result = getSeason()
      expect(result).toBe(Season.WINTER)
    })

    it('should return none', () => {
      const now = DateTime.local().setZone('utc', {
        keepLocalTime: true,
      })
      jest
        .spyOn(DateTime, 'local')
        .mockReturnValueOnce(now.set({ day: 1, month: 10, year: 2021 }))
      const result = getSeason()
      expect(result).toBe(Season.NONE)
    })
  })

  describe('getChallengeTitleWithLineReturn test', () => {
    it('should return Simone\\nVEILLE', () => {
      expect(getChallengeTitleWithLineReturn('CHALLENGE0001')).toBe(
        'Simone\nVEILLE'
      )
    })
    it('should return undefined', () => {
      expect(getChallengeTitleWithLineReturn('CHALLENGE0000')).toBe(undefined)
    })
  })

  describe('getMonthFullName', () => {
    it('should return the name of the month', () => {
      expect(getMonthFullName(3)).toBe('Mars')
    })
  })

  describe('getMonthFullName', () => {
    it('should return the name of the month', () => {
      expect(getMonthName(DateTime.local(2023, 6, 1))).toBe('juin')
    })
  })
  describe('getMonthNameWithPrep', () => {
    it('should return the name of the month with " de " ', () => {
      const date = DateTime.fromISO('2020-11-29T23:59:59.999Z')
      expect(getMonthNameWithPrep(date)).toBe('de novembre')
    })

    it('should return the name of the month with " d\'" ', () => {
      const date = DateTime.fromISO('2020-10-29T23:59:59.999Z')
      expect(getMonthNameWithPrep(date)).toBe('d’octobre')
    })
  })

  describe('getFluidName', () => {
    it('should return electricity', () => {
      expect(getFluidName(FluidType.ELECTRICITY)).toBe('electricity')
    })
    it('should return water', () => {
      expect(getFluidName(FluidType.WATER)).toBe('water')
    })
    it('should return gas', () => {
      expect(getFluidName(FluidType.GAS)).toBe('gas')
    })
    it('should return multifluid', () => {
      expect(getFluidName(FluidType.MULTIFLUID)).toBe('multifluid')
    })
  })

  describe('formatListWithAnd', () => {
    it('should return empty string', () => {
      expect(formatListWithAnd([])).toBe('')
    })
    it('should return single element', () => {
      expect(formatListWithAnd(['pomme'])).toBe('pomme')
    })
    it('should return two elements joined by "et"', () => {
      expect(formatListWithAnd(['pomme', 'banane'])).toBe('pomme et banane')
    })
    it('should return elements joined by commas except the last one with "et"', () => {
      expect(formatListWithAnd(['pomme', 'banane', 'cerise'])).toBe(
        'pomme, banane et cerise'
      )
    })
  })
})