import { HTTP_STATUS } from 'camino-common/src/http'
import { RestNewGetCall } from '../../server/rest'
import { CaminoApiError } from '../../types'
import { EffectDbQueryAndValidateErrors } from '../../pg-database'
import { Effect, Match } from 'effect'
import { GetMutation, Mutation } from 'camino-common/src/mutations'
import { canReadMutation } from 'camino-common/src/permissions/mutation'
import { getMutation, GetMutationErrors, getMutations } from './mutations.queries'

export const getRestMutations: RestNewGetCall<'/rest/mutations'> = (rootPipe): Effect.Effect<Mutation[], CaminoApiError<EffectDbQueryAndValidateErrors | typeof droitsInsuffisants>> =>
  rootPipe.pipe(
    Effect.filterOrFail(
      ({ user }) => canReadMutation(user),
      () => ({ message: droitsInsuffisants })
    ),
    Effect.flatMap(({ pool, searchParams }) => getMutations(pool, searchParams.emails)),
    Effect.map(result => result.map(value => ({ ...value, datetime: value.datetime.toISOString() }))),
    Effect.mapError(caminoError =>
      Match.value(caminoError.message).pipe(
        Match.whenOr('Droits insuffisants', () => ({
          ...caminoError,
          status: HTTP_STATUS.FORBIDDEN,
        })),
        Match.whenOr("Impossible d'exécuter la requête dans la base de données", 'Les données en base ne correspondent pas à ce qui est attendu', () => ({
          ...caminoError,
          status: HTTP_STATUS.INTERNAL_SERVER_ERROR,
        })),
        Match.exhaustive
      )
    )
  )

const droitsInsuffisants = 'Droits insuffisants' as const
export const getRestMutation: RestNewGetCall<'/rest/mutations/:mutationId'> = (rootPipe): Effect.Effect<GetMutation, CaminoApiError<GetMutationErrors | typeof droitsInsuffisants>> =>
  rootPipe.pipe(
    Effect.filterOrFail(
      ({ user }) => canReadMutation(user),
      () => ({ message: droitsInsuffisants })
    ),
    Effect.flatMap(({ pool, params }) => getMutation(pool, params.mutationId)),
    Effect.map(value => ({ ...value, datetime: value.datetime.toISOString(), body: JSON.stringify(value.body) })),
    Effect.mapError(caminoError =>
      Match.value(caminoError.message).pipe(
        Match.whenOr("Impossible d'exécuter la requête dans la base de données", 'Les données en base ne correspondent pas à ce qui est attendu', () => ({
          ...caminoError,
          status: HTTP_STATUS.INTERNAL_SERVER_ERROR,
        })),
        Match.whenOr('Droits insuffisants', () => ({
          ...caminoError,
          status: HTTP_STATUS.FORBIDDEN,
        })),
        Match.whenOr('Élément non trouvé dans la base de données', () => ({
          ...caminoError,
          status: HTTP_STATUS.NOT_FOUND,
        })),
        Match.exhaustive
      )
    )
  )
