import { canReadTitre } from 'camino-common/src/permissions/titres'
import { QuickAccessResult } from 'camino-common/src/titres'
import { HTTP_STATUS } from 'camino-common/src/http'
import { Effect, Match } from 'effect'
import { CaminoApiError } from '../../types'
import { RestNewGetCall } from '../../server/rest'
import { EffectDbQueryAndValidateErrors } from '../../pg-database'
import { getTitresByNom, getTitresByReference } from './quick-access.queries'
import { getAdministrationsLocalesByTitreId, getTitulairesAmodiatairesByTitreId } from './titres.queries'
import { isNullOrUndefinedOrEmpty } from 'camino-common/src/typescript-tools'

const errorCanReadTitre = "Erreur lors de l'accès aux permissions" as const
type QuickAccessSearchErrors = EffectDbQueryAndValidateErrors | typeof errorCanReadTitre

export const quickAccessSearch: RestNewGetCall<'/rest/quickAccess'> = (rootPipe): Effect.Effect<QuickAccessResult[], CaminoApiError<QuickAccessSearchErrors>> => {
  return rootPipe.pipe(
    Effect.bind('unfilteredTitres', ({ searchParams, pool }) =>
      getTitresByNom(pool, searchParams.search).pipe(
        Effect.flatMap(result => {
          if (isNullOrUndefinedOrEmpty(result)) {
            return getTitresByReference(pool, searchParams.search)
          } else {
            return Effect.succeed(result)
          }
        })
      )
    ),
    Effect.bind('filteredTitres', ({ unfilteredTitres, user, pool }) =>
      Effect.tryPromise({
        try: async () => {
          const titres = []
          for (const titre of unfilteredTitres) {
            if (
              await canReadTitre(
                user,
                () => Promise.resolve(titre.type_id),
                () => getAdministrationsLocalesByTitreId(pool, titre.id),
                () => getTitulairesAmodiatairesByTitreId(pool, titre.id),
                titre
              )
            ) {
              titres.push(titre)
            }
          }
          return titres
        },
        catch: e => ({ message: errorCanReadTitre, extra: e }),
      })
    ),
    Effect.map(({ filteredTitres }) => filteredTitres.map<QuickAccessResult>(titre => ({ id: titre.id, nom: titre.nom, typeId: titre.type_id, titreDateDebut: titre.demarche_date_debut }))),
    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', "Erreur lors de l'accès aux permissions", () => ({
          ...caminoError,
          status: HTTP_STATUS.INTERNAL_SERVER_ERROR,
        })),
        Match.exhaustive
      )
    )
  )
}
