import Model from '~/services/serializer/normalizer/model'
import {AnyJson, DataPersisterArgs} from '~/types/interfaces'
import { QUERY_TYPE } from '~/types/enums'
import { repositoryHelper } from '~/services/store/repository'
import User from '~/tests/unit/fixture/models/User'
import { createStore } from '~/tests/unit/Helpers'
import {queryHelper} from "~/services/store/query";

jest.mock('~/services/store/repository')
const repositoryHelperMock = repositoryHelper as jest.Mocked<typeof repositoryHelper>

jest.mock('~/services/store/query')
const queryHelperMock = queryHelper as jest.Mocked<typeof queryHelper>

describe('support()', () => {
  it('should support model query type', () => {
    expect(Model.support(QUERY_TYPE.MODEL)).toBeTruthy()
  })

  it('should not support default type', () => {
    expect(Model.support(QUERY_TYPE.DEFAULT)).toBeFalsy()
  })

  it('should not support enum type', () => {
    expect(Model.support(QUERY_TYPE.ENUM)).toBeFalsy()
  })
})

describe('normalize()', () => {
  it('should not permit args without model', () => {
    const args: DataPersisterArgs = {
      type: QUERY_TYPE.MODEL
    }
    expect(() => Model.normalize(args)).toThrowError('*args* has no model attribute')
  })

  it('should not permit normalize without item', async () => {
    const args:DataPersisterArgs = {
      type: QUERY_TYPE.MODEL,
      model: User,
      id: 1
    }
    expect(() => Model.normalize(args)).toThrowError('Item not found')
  })

  it('should find an item thanks to a repository, and normalize it to JSON', async () => {
    const store = createStore()
    const user = store.$repo(User).make()
    repositoryHelperMock.findItemFromModel = jest.fn().mockReturnValue(user)

    const args:DataPersisterArgs = {
      type: QUERY_TYPE.MODEL,
      model: User,
      id: 1
    }
    expect(Model.normalize(args)).toStrictEqual({ id: 1, name: 'John Doe' })
  })

  it('should find an item thanks to a query, and normalize it to JSON', async () => {
    const store = createStore()
    const user = store.$repo(User).make()
    const query = store.$repo(User).query()
    queryHelperMock.getItem = jest.fn().mockReturnValue(user)

    const args:DataPersisterArgs = {
      type: QUERY_TYPE.MODEL,
      model: User,
      id: 1,
      query: query
    }
    expect(Model.normalize(args)).toStrictEqual({ id: 1, name: 'John Doe' })
  })
})

describe('isPostQuery()', () => {
  it('should return true if args has got a temp ID', () => {
    const args:DataPersisterArgs = {
      type: QUERY_TYPE.MODEL,
      idTemp: 1
    }
    expect(Model.isPostQuery(args)).toBeTruthy()
  })

  it('should return false if args has not a temp ID', () => {
    const args:DataPersisterArgs = {
      type: QUERY_TYPE.MODEL
    }
    expect(Model.isPostQuery(args)).toBeFalsy()
  })
})

describe('sanitizeBeforePost()', () => {
  it('should return data without id', () => {
    const data:AnyJson = {
      id: 1,
      foo: 'bar',
      embedded:{
        id:2,
        bar: 'foo'
      }
    }
    expect(Model.sanitizeBeforePost(data, ['embedded'])).toEqual({foo:'bar', embedded:{bar: 'foo'}})
  })
})
