import { newEntrepriseId } from 'camino-common/src/entreprise'
import { Role, UserNotNull } from 'camino-common/src/roles'
import { AdministrationId } from 'camino-common/src/static/administrations'
import { testBlankUser } from 'camino-common/src/tests-utils'
import { test, expect, vi } from 'vitest'
import { utilisateurUpdationValidate } from './utilisateur-updation-validate'
import { newUtilisateurId } from '../../database/models/_format/id-create'
import { callAndExit } from '../../tools/fp-tools'

const users: Record<Role, UserNotNull> = {
  super: { ...testBlankUser, role: 'super' },
  admin: { ...testBlankUser, role: 'admin', administrationId: 'aut-97300-01' },
  editeur: {
    ...testBlankUser,
    role: 'editeur',
    administrationId: 'aut-97300-01',
  },
  lecteur: {
    ...testBlankUser,
    role: 'lecteur',
    administrationId: 'aut-97300-01',
  },
  entreprise: { ...testBlankUser, role: 'entreprise', entrepriseIds: [] },
  "bureau d'études": {
    ...testBlankUser,
    role: "bureau d'études",
    entrepriseIds: [],
  },
  defaut: { ...testBlankUser, role: 'defaut' },
}

const fakeAdministrationId = 'fakeAdminId' as AdministrationId

console.error = vi.fn()
test('utilisateurUpdationValidate privilege escalation forbidden', async () => {
  await expect(
    callAndExit(utilisateurUpdationValidate(users.defaut, { ...users.defaut, role: 'super', administrationId: null, entrepriseIds: [] }, users.defaut))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.admin, { ...users.admin, role: 'super', entrepriseIds: [], administrationId: null }, users.admin))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.lecteur, { ...users.lecteur, role: 'super', entrepriseIds: [], administrationId: null }, users.lecteur))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.editeur, { ...users.editeur, role: 'super', entrepriseIds: [], administrationId: null }, users.editeur))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.entreprise, { ...users.entreprise, role: 'super', entrepriseIds: [], administrationId: null }, users.entreprise))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users["bureau d'études"], { ...users["bureau d'études"], role: 'super', entrepriseIds: [], administrationId: null }, users.entreprise))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.editeur, { ...users.editeur, role: 'entreprise', administrationId: null, entrepriseIds: [newEntrepriseId('id')] }, users.editeur))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.defaut, { ...users.defaut, role: 'entreprise', administrationId: null, entrepriseIds: [newEntrepriseId('id')] }, users.defaut))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
})

test('utilisateurUpdationValidate incorrect users throw error', async () => {
  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'super', administrationId: null, entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: l'utilisateur n'existe pas]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'super', entrepriseIds: [newEntrepriseId('entrepriseId')], administrationId: null }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'super', administrationId: 'aut-97300-01', entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'defaut', administrationId: null, entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: l'utilisateur n'existe pas]`)
  await expect(
    callAndExit(
      utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'defaut', entrepriseIds: [newEntrepriseId('entrepriseId')], administrationId: null }, undefined)
    )
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'defaut', administrationId: 'aut-97300-01', entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'admin', administrationId: null, entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'admin', entrepriseIds: [newEntrepriseId('entrepriseId')], administrationId: null }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'admin', administrationId: fakeAdministrationId, entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'entreprise', administrationId: null, entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'entreprise', administrationId: null, entrepriseIds: [] }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)
  await expect(
    callAndExit(
      utilisateurUpdationValidate(
        users.super,
        { id: newUtilisateurId('utilisateurId'), role: 'entreprise', administrationId: fakeAdministrationId, entrepriseIds: [newEntrepriseId('entrepriseId')] },
        undefined
      )
    )
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: utilisateur incorrect]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.super, { id: newUtilisateurId('utilisateurId'), role: 'super', entrepriseIds: [], administrationId: null }, undefined))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: l'utilisateur n'existe pas]`)

  await expect(
    callAndExit(
      utilisateurUpdationValidate(
        users.admin,
        { id: newUtilisateurId('utilisateurId'), role: 'editeur', administrationId: 'aut-97300-01', entrepriseIds: [] },
        { ...testBlankUser, id: newUtilisateurId('fakeId'), role: 'admin', administrationId: 'aut-97300-01' }
      )
    )
  ).resolves.toMatchInlineSnapshot(`
    {
      "administrationId": "aut-97300-01",
      "email": "email@gmail.com",
      "id": "fakeId",
      "nom": "nom",
      "prenom": "prenom",
      "role": "admin",
      "telephone_fixe": null,
      "telephone_mobile": null,
    }
  `)
  await expect(
    callAndExit(
      utilisateurUpdationValidate(
        users.admin,
        { id: newUtilisateurId('utilisateurId'), role: 'admin', administrationId: 'aut-97300-01', entrepriseIds: [] },
        { ...testBlankUser, id: newUtilisateurId('fakeId'), role: 'editeur', administrationId: 'aut-97300-01' }
      )
    )
  ).resolves.toMatchInlineSnapshot(`
    {
      "administrationId": "aut-97300-01",
      "email": "email@gmail.com",
      "id": "fakeId",
      "nom": "nom",
      "prenom": "prenom",
      "role": "editeur",
      "telephone_fixe": null,
      "telephone_mobile": null,
    }
  `)
  await expect(
    callAndExit(
      utilisateurUpdationValidate(
        users.admin,
        { id: newUtilisateurId('utilisateurId'), role: 'editeur', administrationId: 'aut-mrae-guyane-01', entrepriseIds: [] },
        { ...testBlankUser, id: newUtilisateurId('fakeId'), role: 'editeur', administrationId: 'aut-97300-01' }
      )
    )
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(
      utilisateurUpdationValidate(
        users.admin,
        { id: newUtilisateurId('utilisateurId'), role: 'editeur', administrationId: 'aut-97300-01', entrepriseIds: [] },
        { ...testBlankUser, id: newUtilisateurId('fakeId'), role: 'editeur', administrationId: 'aut-mrae-guyane-01' }
      )
    )
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.editeur, { ...users.editeur, administrationId: 'dea-reunion-01', entrepriseIds: [] }, { ...users.editeur }))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(utilisateurUpdationValidate(users.lecteur, { ...users.lecteur, administrationId: 'dea-reunion-01', entrepriseIds: [] }, { ...users.lecteur }))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)

  await expect(
    callAndExit(utilisateurUpdationValidate(users.entreprise, { ...users.entreprise, administrationId: null, entrepriseIds: [newEntrepriseId('newEntreprise')] }, { ...users.entreprise }))
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
  await expect(
    callAndExit(
      utilisateurUpdationValidate(users["bureau d'études"], { ...users["bureau d'études"], administrationId: null, entrepriseIds: [newEntrepriseId('newEntreprise')] }, { ...users["bureau d'études"] })
    )
  ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: droits insuffisants]`)
})
