import { Repository } from '@vuex-orm/core'
import * as _ from 'lodash'
import { createStore } from '~/tests/unit/Helpers'
import User from '~/tests/unit/fixture/models/User'
import { repositoryHelper } from '~/services/store/repository'
import { AnyStore } from '~/types/interfaces'

let store: AnyStore, repository: Repository<User>

beforeEach(() => {
  store = createStore()
  repository = store.$repo(User)
  repositoryHelper.setStore(store)
})

describe('getRepository()', () => {
  it('should return the repository of the Model', () => {
    expect(repositoryHelper.getRepository(User)).toStrictEqual(repository)
  })
})

describe('getEntity()', () => {
  it('should return the entity of the Model', () => {
    expect(repositoryHelper.getEntity(User)).toEqual('users')
  })
})

describe('updateStoreFromField()', () => {
  it('should throw an error if the field doest exist', () => {
    expect(() => repositoryHelper.updateStoreFromField(User, {}, 'Foo Bar', 'name')).toThrowError('field not found')
  })

  it('should update the store', () => {
    const user = repository.make()
    repository.save(user)
    repositoryHelper.updateStoreFromField(User, user.$toJson(), 'Foo Bar', 'name')
    const userUpdate = repository.find(1)
    expect(userUpdate?.$toJson()).toStrictEqual({ id: 1, name: 'Foo Bar' })
  })
})

describe('persist()', () => {
  it('should throw an error if the entry is empty', () => {
    expect(() => repositoryHelper.persist(User, {})).toThrowError()
  })

  it('should persist the entry inside the store', () => {
    const entryExpected = { id: 2, name: 'Alice' }
    repositoryHelper.persist(User, entryExpected)
    const alice = repository.find(2)
    expect(alice?.$toJson()).toStrictEqual(entryExpected)
  })
})

describe('findItemFromModel()', () => {
  it('should throw an error if the Item is not found', () => {
    expect(() => repositoryHelper.findItemFromModel(User, 1)).toThrowError('Item not found')
  })

  it('should return the correct item of the Model', () => {
    const user = repository.make()
    repository.save(user)
    expect(repositoryHelper.findItemFromModel(User, 1)).toStrictEqual(user)
  })
})

describe('findCollectionFromModel()', () => {
  it('should return the correct collection of the Model', () => {
    const UsersArray: Array<User> = []
    const user = repository.make()
    UsersArray.push(user)
    repository.save(user)

    const user2 = _.cloneDeep(user)
    user2.id = 2
    user2.name = 'Foo Bar'
    UsersArray.push(user2)
    repository.save(user2)
    expect(repositoryHelper.findCollectionFromModel(User)).toStrictEqual(UsersArray)
  })
})

describe('cleanRepository()', () => {
  it('should clean the entire repository', () => {
    const user = repository.make()
    repository.save(user)
    repositoryHelper.cleanRepository(User)
    expect(repository.all()).toEqual([])
  })
})
