import {IBook} from '../models/IBook'
import {faker} from '@faker-js/faker'
import {
  BOOKS_STORAGE_KEY,
  persistToDatabase,
  retrieveFromDatabase,
} from './NIET_OPENEN_WORDT_GEBRUIKT_DOOR_DE_API_FILES/databaseSimulation.ts'

import {books} from './NIET_OPENEN_WORDT_GEBRUIKT_DOOR_DE_API_FILES/data/books.ts'

//region Mutations & queries

/**
 * ---------------------------------------------------------------------------------------------------------------------
 *                                          MUTATIONS & QUERIES
 * ---------------------------------------------------------------------------------------------------------------------
 */

//endregion

//region API functions

/**
 * ---------------------------------------------------------------------------------------------------------------------
 *                                          API functions
 * ---------------------------------------------------------------------------------------------------------------------
 */

/**
 * Haal alle boeken op uit de database.
 */
const getBooks = (): Promise<IBook[]> => {
  return retrieveFromDatabase<IBook[]>(BOOKS_STORAGE_KEY)
}

/**
 * Haal een willekeurig boek op uit de database.
 * @param id Het id van het boek dat verwijderd moet worden.
 */
const getBook = async (id: number): Promise<IBook> => {
  const books = await getBooks()
  return books.find(s => s.id === id)!
}

interface DeleteBookParams {
  id: number
}

/**
 * Verwijder een specifiek boek uit de database.
 * @param id Het id van het boek dat verwijderd moet worden.
 */
const deleteBook = async ({id}: DeleteBookParams): Promise<void> => {
  const books = await getBooks()
  const newBooks = books.filter(b => b.id !== id)
  await persistToDatabase(BOOKS_STORAGE_KEY, newBooks)
}

/**
 * Voeg een nieuw willekeurig boek toe aan de database.
 */
const addBook = async (): Promise<IBook> => {
  const allBooks = books
  const booksInDB = await getBooks()
  const booksInDBIds = new Set(booksInDB.map(b => b.id))

  const filteredBooks = allBooks.filter(b => !booksInDBIds.has(b.id))
  if (filteredBooks.length === 0) {
    throw new Error('No more books to add, please reset the database before trying again.')
  }

  const selectedBook = faker.helpers.arrayElement(filteredBooks)

  await persistToDatabase(BOOKS_STORAGE_KEY, [...booksInDB, selectedBook])
  return selectedBook
}

//endregion
