import type {Prisma, Tag} from '@/generated/prisma/client'
import {prismaClient} from './prismaClient'
import type {TagWithContacts} from '@/models/tags'
import {tagWithContactsInclude} from '@/models/tags'

export type CreateTagParams = Prisma.TagCreateInput

/**
 * Create a new tag.
 */
export async function createTag(tagInput: CreateTagParams): Promise<Tag> {
  return prismaClient.tag.create({data: tagInput})
}

/**
 * Retrieve all tags.
 */
export async function getTags(): Promise<Tag[]> {
  return prismaClient.tag.findMany()
}

/**
 * Get a specific tag from the database.
 *
 * @param id The id of the tag to retrieve.
 */
export async function getTag(id: string): Promise<TagWithContacts> {
  return prismaClient.tag.findUniqueOrThrow({
    where: {id},
    include: tagWithContactsInclude,
  })
}

/**
 * Delete a tag.
 *
 * @param id The id of the tag to delete.
 */
export async function deleteTag(id: string): Promise<void> {
  await prismaClient.tag.delete({where: {id}})
}

export type UpdateTagParams = Prisma.TagUpdateInput & {id: string}

/**
 * Update a tag.
 *
 * @param tag The updated tag information.
 */
export async function updateTag(tag: UpdateTagParams): Promise<Tag> {
  return prismaClient.tag.update({where: {id: tag.id}, data: tag})
}

/**
 * Link a tag to a contact.
 *
 * @param tagId The id of the tag for which to link the contacts.
 * @param contactIds The ids of the contacts to connect to the tag.
 */
export async function linkTagsToContact(tagId: string, contactIds: string[]): Promise<void> {
  await prismaClient.tag.update({
    where: {id: tagId},
    data: {
      contacts: {
        connect: contactIds.map(id => ({id})),
      },
    },
  })
}

/**
 * Remove a tag from a contact.
 *
 * @param tagId The id of the tag from which to remove the contacts.
 * @param contactIds The ids of the contacts to remove from the tag.
 */
export async function disconnectTagsFromContact(tagId: string, contactIds: string[]): Promise<void> {
  await prismaClient.tag.update({
    where: {id: tagId},
    data: {
      contacts: {
        disconnect: contactIds.map(id => ({id})),
      },
    },
  })
}
