import { HTTP_STATUS } from 'camino-common/src/http'

import { AdminUserNotNull } from 'camino-common/src/roles'
import { canReadAdministrations } from 'camino-common/src/permissions/administrations'
import { deleteAdministrationActiviteTypeEmail, getActiviteTypeEmailsByAdministrationId, getUtilisateursByAdministrationId, insertAdministrationActiviteTypeEmail } from './administrations.queries'
import { AdministrationActiviteTypeEmail } from 'camino-common/src/administrations'
import { CaminoApiError } from '../../types'
import { EffectDbQueryAndValidateErrors } from '../../pg-database'
import { Effect, Match } from 'effect'
import { RestNewGetCall, RestNewPostCall } from '../../server/rest'

const accessInterdit = 'Accès interdit' as const
type GetAdministrationUtilisateursErreurs = EffectDbQueryAndValidateErrors | typeof accessInterdit
export const getAdministrationUtilisateurs: RestNewGetCall<'/rest/administrations/:administrationId/utilisateurs'> = (
  rootPipe
): Effect.Effect<AdminUserNotNull[], CaminoApiError<GetAdministrationUtilisateursErreurs>> =>
  rootPipe.pipe(
    Effect.filterOrFail(
      ({ user }) => canReadAdministrations(user),
      () => ({ message: accessInterdit })
    ),
    Effect.flatMap(({ pool, params }) => getUtilisateursByAdministrationId(pool, params.administrationId)),
    Effect.mapError(caminoError =>
      Match.value(caminoError.message).pipe(
        Match.when('Accès interdit', () => ({ ...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
      )
    )
  )

type GetAdministrationActiviteTypeEmailsErreurs = EffectDbQueryAndValidateErrors | typeof accessInterdit
export const getAdministrationActiviteTypeEmails: RestNewGetCall<'/rest/administrations/:administrationId/activiteTypeEmails'> = (
  rootPipe
): Effect.Effect<AdministrationActiviteTypeEmail[], CaminoApiError<GetAdministrationActiviteTypeEmailsErreurs>> =>
  rootPipe.pipe(
    Effect.filterOrFail(
      ({ user }) => canReadAdministrations(user),
      () => ({ message: accessInterdit })
    ),
    Effect.flatMap(({ pool, params }) => getActiviteTypeEmailsByAdministrationId(pool, params.administrationId)),
    Effect.mapError(caminoError =>
      Match.value(caminoError.message).pipe(
        Match.when('Accès interdit', () => ({ ...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
      )
    )
  )

export const addAdministrationActiviteTypeEmails: RestNewPostCall<'/rest/administrations/:administrationId/activiteTypeEmails'> = (
  rootPipe
): Effect.Effect<boolean, CaminoApiError<typeof accessInterdit | EffectDbQueryAndValidateErrors>> => {
  return rootPipe.pipe(
    Effect.filterOrFail(
      ({ user }) => canReadAdministrations(user),
      () => ({ message: accessInterdit })
    ),
    Effect.flatMap(({ pool, params, body }) => insertAdministrationActiviteTypeEmail(pool, params.administrationId, body)),
    Effect.mapError(caminoError =>
      Match.value(caminoError.message).pipe(
        Match.when('Accès interdit', () => ({ ...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
      )
    )
  )
}

export const deleteAdministrationActiviteTypeEmails: RestNewPostCall<'/rest/administrations/:administrationId/activiteTypeEmails/delete'> = (
  rootPipe
): Effect.Effect<boolean, CaminoApiError<typeof accessInterdit | EffectDbQueryAndValidateErrors>> => {
  return rootPipe.pipe(
    Effect.filterOrFail(
      ({ user }) => canReadAdministrations(user),
      () => ({ message: accessInterdit })
    ),
    Effect.flatMap(({ pool, params, body }) => deleteAdministrationActiviteTypeEmail(pool, params.administrationId, body)),
    Effect.mapError(caminoError =>
      Match.value(caminoError.message).pipe(
        Match.when('Accès interdit', () => ({ ...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
      )
    )
  )
}
