import {faker} from '@faker-js/faker'

import {
  persistToDatabase,
  retrieveFromDatabase,
  STORAGE_KEY,
} from '@/api/NIET_OPENEN_WORDT_GEBRUIKT_DOOR_DE_API_FILES/databaseSimulation.ts'
import type {IArtifact} from '@/models/IArtifact.ts'
import {artifacts} from '@/api/NIET_OPENEN_WORDT_GEBRUIKT_DOOR_DE_API_FILES/data/artifacts.ts'

//region Mutations & queries

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

//endregion

//region API functions

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

/**
 * Haal alle artefacten op uit de database.
 */
const getArtifacts = (): Promise<IArtifact[]> => {
  return retrieveFromDatabase<IArtifact[]>(STORAGE_KEY)
}

/**
 * Haal een specifiek artefact op uit de database.
 *
 * @param id Het id van het artefact dat opgehaald moet worden.
 */
const getArtifact = async (id: number): Promise<IArtifact> => {
  const artifacts = await getArtifacts()
  return artifacts.find(s => s.id === id)!
}

interface DeleteArtifactParams {
  id: number
}

/**
 * Verwijder een specifiek artefact uit de database.
 *
 * @param id Het id van het artefact dat verwijderd moet worden.
 */
const deleteArtifact = async ({id}: DeleteArtifactParams): Promise<void> => {
  // Wait 1.5 seconds to display the delete animation.
  await new Promise(r => setTimeout(r, 1000))
  let artifacts = await getArtifacts()
  artifacts = artifacts.filter(a => a.id !== id)
  await persistToDatabase(
    STORAGE_KEY,
    artifacts.filter(b => b.id !== id),
  )
}

interface UpdateArtifactParams {
  id: number
  artifact: Partial<IArtifact>
}

const updateArtifact = async ({id, artifact}: UpdateArtifactParams): Promise<IArtifact> => {
  const artifacts = await getArtifacts()
  const updateIndex = artifacts.findIndex(a => a.id === id)
  artifacts[updateIndex] = {
    ...artifacts[updateIndex],
    ...artifact,
  }
  await persistToDatabase(STORAGE_KEY, artifacts)
  return artifacts[updateIndex]
}

/**
 * Voeg een nieuw willekeurig pokemon toe aan de database.
 */
const addArtefact = async (): Promise<IArtifact> => {
  const allArtifacts = artifacts
  const artifactsInDB = await getArtifacts()
  const dbIds = new Set(artifactsInDB.map(b => b.id))

  const filteredArtifacts = allArtifacts.filter(b => !dbIds.has(b.id))
  if (filteredArtifacts.length === 0) {
    throw new Error('All 35 artifacts have already been added to the museum collection.')
  }

  const selectedArtifact = faker.helpers.arrayElement(filteredArtifacts)

  await persistToDatabase(STORAGE_KEY, [...artifactsInDB, selectedArtifact])
  return selectedArtifact
}
