import MockDate from 'mockdate'
import moment from 'moment'
import dayjs from '../../src'
import updateLocale from '../../src/plugin/updateLocale'
import localizedFormat from '../../src/plugin/localizedFormat'
import '../../src/locale/zh-cn'

dayjs.extend(updateLocale)
dayjs.extend(localizedFormat)

beforeEach(() => {
  MockDate.set(new Date())
})

afterEach(() => {
  MockDate.reset()
})

const newLocale = {
  months: new Array(12).fill('testMonth'),
  formats: { // formats for dayjs and longDateFormat for momentjs
    LT: '[testFormat]'
  },
  longDateFormat: {
    LT: '[testFormat]'
  }
}

const formatString = 'MMMM LT'

describe('Update locale', () => {
  it('Invalid argument', () => {
    const result = dayjs.updateLocale('InvalidLocaleName', {})
    expect(result)
      .toEqual(undefined)
    expect(dayjs().format(formatString))
      .toEqual(moment().format(formatString))
  })

  it('Return value', () => {
    const result1 = dayjs.updateLocale('en')
    expect(typeof result1).toEqual('object')
    const result2 = dayjs.updateLocale('en', {})
    expect(typeof result2).toEqual('object')
    const result3 = dayjs.updateLocale('en', newLocale)
    expect(typeof result3).toEqual('object')
  })

  it('Update build-in en locale', () => {
    moment.updateLocale('en', newLocale)
    dayjs.updateLocale('en', newLocale)

    expect(dayjs().format(formatString))
      .toEqual('testMonth testFormat')

    expect(dayjs().format(formatString))
      .toEqual(moment().format(formatString))
  })

  it('Update imported zh-cn locale', () => {
    moment.updateLocale('zh-cn', newLocale)
    dayjs.updateLocale('zh-cn', newLocale)
    dayjs.locale('zh-cn')
    moment.locale('zh-cn')
    expect(dayjs().format(formatString))
      .toEqual('testMonth testFormat')

    expect(dayjs().format(formatString))
      .toEqual(moment().format(formatString))
  })

  it('Partial update to nested object (formats)', () => {
    dayjs.locale('en')
    // First, get the original formats
    const originalLocale = dayjs.Ls.en
    const originalLT = originalLocale.formats && originalLocale.formats.LT

    // Update only L format
    dayjs.updateLocale('en', {
      formats: {
        L: 'DD/MM/YYYY'
      }
    })

    const updatedLocale = dayjs.Ls.en
    // The updated key should have the new value
    expect(updatedLocale.formats.L).toBe('DD/MM/YYYY')
    // Other keys in formats should be preserved
    expect(updatedLocale.formats.LT).toBe(originalLT)
  })

  it('Non-object values should still be replaced entirely', () => {
    const newMonths = new Array(12).fill('newMonth')
    dayjs.updateLocale('en', {
      months: newMonths
    })
    const updatedLocale = dayjs.Ls.en
    expect(updatedLocale.months).toEqual(newMonths)
  })

  it('Update invalid date string', () => {
    const locale = 'en'
    const localeSetting = { invalidDate: 'bad date' }
    dayjs.updateLocale(locale, localeSetting)
    moment.updateLocale(locale, localeSetting)
    dayjs.locale(locale)
    moment.locale(locale)
    expect(dayjs('').format()).toBe(moment('').format())
    expect(dayjs('otherString').format()).toBe(moment('otherString').format())
  })
})
