import { ITitreEtape } from '../../types'

import { getPossiblesEtapesTypes, titreDemarcheUpdatedEtatValidate } from './titre-demarche-etat-validate'
import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create'
import { EtapesTypesEtapesStatuts } from 'camino-common/src/static/etapesTypesEtapesStatuts'
import { describe, test, expect, vi } from 'vitest'
import { caminoDateValidator, dateAddDays, firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date'
import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes'
import { ETAPE_IS_BROUILLON, ETAPE_IS_NOT_BROUILLON, etapeIdValidator } from 'camino-common/src/etape'
import { TitreEtapeForMachine } from '../rules-demarches/machine-common'
import { communeIdValidator, toCommuneId } from 'camino-common/src/static/communes'
import { km2Validator } from 'camino-common/src/number'
import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts'
import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes'
import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes'
import { MachineInfo } from 'camino-common/src/machines'
import { ApiMachineInfo } from '../rules-demarches/machines'
import { throwableMachineInfoForTestsOnly } from '../../../tests/_utils'

console.warn = vi.fn()

describe('titreDemarcheUpdatedEtatValidate', () => {
  test('ajoute une étape à une démarche vide', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, null)
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        typeId: 'mfr',
        date: caminoDateValidator.parse('2030-01-01'),
        isBrouillon: ETAPE_IS_BROUILLON,
        statutId: 'fai',
        contenu: {},
        communes: [],
        surface: null,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      []
    )

    expect(valid.valid).toBe(true)
  })

  test('ajoute une étape à une démarche qui contient déjà une étape', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2022-05-03'))
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        typeId: 'men',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-05-04'),
        communes: null,
        contenu: null,
        surface: null,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      [
        {
          id: newEtapeId('1'),
          typeId: 'mfr',
          statutId: 'fai',
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          date: toCaminoDate('2022-05-03'),
          communes: null,
          contenu: null,
          ordre: 1,
          surface: null,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
      ]
    )

    expect(valid.valid).toBe(true)
  })

  test('prend en compte les données des étapes pour la machine', () => {
    const demarcheId = newDemarcheId()
    const demande: Pick<
      ITitreEtape,
      'id' | 'statutId' | 'ordre' | 'typeId' | 'date' | 'contenu' | 'surface' | 'communes' | 'isBrouillon' | 'concurrence' | 'hasTitreFrom' | 'demarcheIdsConsentement'
    > = {
      id: etapeIdValidator.parse('idMfr'),
      typeId: 'mfr',
      statutId: 'fai',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      date: toCaminoDate('2020-10-22'),
      communes: [{ id: communeIdValidator.parse('97333') }],
      ordre: 1,
      contenu: null,
      surface: km2Validator.parse(51),
      concurrence: { amIFirst: true },
      hasTitreFrom: true,
      demarcheIdsConsentement: [],
    }
    const machineInfo = MachineInfo.withDate('prm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-12-17'))
    const valid = titreDemarcheUpdatedEtatValidate(machineInfo, [{ id: demarcheId }], demande, [
      demande,
      {
        id: etapeIdValidator.parse('idMdp'),
        typeId: 'men',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2020-12-17'),
        ordre: 2,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      {
        id: etapeIdValidator.parse('idSpp'),
        typeId: 'spp',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2021-01-18'),
        ordre: 3,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      {
        id: etapeIdValidator.parse('idMcr'),
        typeId: 'mcr',
        statutId: 'fav',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-11-17'),
        ordre: 4,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      {
        id: etapeIdValidator.parse('idAnf'),
        typeId: 'anf',
        statutId: 'ter',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-11-17'),
        ordre: 5,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      {
        id: etapeIdValidator.parse('idAsc'),
        typeId: 'asc',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-11-17'),
        ordre: 6,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      {
        id: etapeIdValidator.parse('idAdc'),
        typeId: 'adc',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-11-17'),
        ordre: 7,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      {
        id: etapeIdValidator.parse('idApo'),
        typeId: 'apo',
        statutId: 'fav',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2023-02-08'),
        ordre: 8,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
    ])

    expect(valid).toMatchInlineSnapshot(`
        {
          "errors": null,
          "valid": true,
        }
      `)
  })

  test('modifie une étape à une démarche', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2022-05-04'))
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        id: newEtapeId('1'),
        typeId: 'mfr',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-05-04'),
        communes: null,
        contenu: null,
        surface: null,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      [
        {
          id: newEtapeId('1'),
          typeId: 'mfr',
          date: toCaminoDate('2022-05-03'),
          statutId: 'fai',
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          communes: null,
          contenu: null,
          ordre: 1,
          surface: null,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
        {
          id: newEtapeId('2'),
          typeId: 'men',
          date: toCaminoDate('2022-05-05'),
          statutId: 'fai',
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          communes: null,
          contenu: null,
          ordre: 2,
          surface: null,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
      ]
    )

    expect(valid.valid, JSON.stringify(valid)).toBe(true)
  })

  test('l’ajout d’une étape d’une démarche historique est valide', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2000-01-01'))
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        typeId: 'mfr',
        isBrouillon: ETAPE_IS_BROUILLON,
        date: caminoDateValidator.parse('2000-02-02'),
        statutId: 'fai',
        concurrence: { amIFirst: true },
        demarcheIdsConsentement: [],
        hasTitreFrom: true,
      },
      [
        {
          id: etapeIdValidator.parse('1'),
          typeId: ETAPES_TYPES.demande,
          date: caminoDateValidator.parse('2000-01-01'),
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          statutId: ETAPES_STATUTS.FAIT,
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          demarcheIdsConsentement: [],
        },
      ],
      false
    )

    expect(valid).toMatchInlineSnapshot(`
      {
        "errors": null,
        "valid": true,
      }
    `)
  })

  test('l’ajout d’une étape à une démarche sans étape est valide', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, null)
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        typeId: ETAPES_TYPES.demande,
        isBrouillon: ETAPE_IS_BROUILLON,
        date: caminoDateValidator.parse('2000-01-01'),
        statutId: ETAPES_STATUTS.FAIT,
        concurrence: { amIFirst: true },
        demarcheIdsConsentement: [],
        hasTitreFrom: true,
      },
      []
    )

    expect(valid.valid).toBe(true)
  })

  test("retourne une erreur si la démarche en cours de modification n'existe pas", () => {
    const demarcheId = newDemarcheId()
    const etapeDate = caminoDateValidator.parse('2000-01-01')
    expect(
      titreDemarcheUpdatedEtatValidate(
        MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(etapeDate)),
        [{ id: newDemarcheId() }],
        {
          id: etapeIdValidator.parse('1'),
          typeId: ETAPES_TYPES.demande,
          date: etapeDate,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          statutId: ETAPES_STATUTS.FAIT,
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          demarcheIdsConsentement: [],
        },
        []
      )
    ).toMatchInlineSnapshot(`
      {
        "errors": [
          "le titre ne contient pas la démarche en cours de modification",
        ],
        "valid": false,
      }
    `)

    const newEtapeDate = caminoDateValidator.parse('2025-01-01')
    expect(
      titreDemarcheUpdatedEtatValidate(
        MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(newEtapeDate)),
        [{ id: demarcheId }],
        {
          id: etapeIdValidator.parse('1'),
          typeId: ETAPES_TYPES.demande,
          date: newEtapeDate,
          concurrence: { amIFirst: true },
          hasTitreFrom: false,
          statutId: ETAPES_STATUTS.FAIT,
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          demarcheIdsConsentement: [],
          communes: [{ id: toCommuneId('97300') }],
          surface: km2Validator.parse(12),
        },
        []
      )
    ).toMatchInlineSnapshot(`
      {
        "errors": null,
        "valid": true,
      }
    `)
  })

  test('supprime une étape', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2003-01-01'))
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        id: etapeIdValidator.parse('1'),
        typeId: 'mfr',
        date: caminoDateValidator.parse('2023-01-01'),
        statutId: 'fai',
        isBrouillon: ETAPE_IS_BROUILLON,
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      [
        {
          id: etapeIdValidator.parse('1'),
          typeId: 'mfr',
          date: caminoDateValidator.parse('2023-01-01'),
          statutId: 'fai',
          isBrouillon: ETAPE_IS_BROUILLON,
          ordre: 1,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
      ],
      true
    )

    expect(valid.valid).toBe(true)
  })

  test('ajoute une étape à une démarche sans machine', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, null)
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        id: etapeIdValidator.parse('1'),
        typeId: ETAPES_TYPES.demande,
        date: caminoDateValidator.parse('1030-01-01'),
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        statutId: ETAPES_STATUTS.FAIT,
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        demarcheIdsConsentement: [],
      },
      []
    )

    expect(valid.valid).toBe(true)
  })

  test('ajoute une demande en construction à une démarche vide', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = throwableMachineInfoForTestsOnly('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, null)
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        id: etapeIdValidator.parse('1'),
        typeId: ETAPES_TYPES.demande,
        date: caminoDateValidator.parse('2030-01-01'),
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        statutId: ETAPES_STATUTS.FAIT,
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        demarcheIdsConsentement: [],
        communes: [{ id: toCommuneId('97300') }],
        surface: km2Validator.parse(12),
      },
      []
    )

    expect(valid).toMatchInlineSnapshot(`
      {
        "errors": null,
        "valid": true,
      }
    `)
  })

  test('ajoute une demande en construction à une démarche qui contient déjà une étape', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-01'))
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        typeId: 'mfr',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_BROUILLON,
        date: caminoDateValidator.parse('2024-01-01'),
        concurrence: { amIFirst: true },
        demarcheIdsConsentement: [],
        hasTitreFrom: true,
      },
      [
        {
          id: etapeIdValidator.parse('1'),
          date: caminoDateValidator.parse('2020-01-01'),
          typeId: 'dae',
          statutId: 'exe',
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          ordre: 1,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
      ]
    )

    expect(valid.valid).toBe(true)
  })

  test('modifie une demande en construction à une démarche', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-01'))
    const valid = titreDemarcheUpdatedEtatValidate(
      machineInfo,
      [{ id: demarcheId }],
      {
        id: etapeIdValidator.parse('1'),
        typeId: 'mfr',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_BROUILLON,
        date: caminoDateValidator.parse('2024-01-01'),
        concurrence: { amIFirst: true },
        hasTitreFrom: true,
        demarcheIdsConsentement: [],
      },
      [
        {
          id: etapeIdValidator.parse('1'),
          typeId: 'mfr',
          statutId: 'fai',
          isBrouillon: ETAPE_IS_BROUILLON,
          date: caminoDateValidator.parse('2024-01-01'),
          ordre: 2,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
        {
          id: etapeIdValidator.parse('2'),
          typeId: 'dae',
          date: caminoDateValidator.parse('2020-01-01'),
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          statutId: 'exe',
          ordre: 1,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
      ]
    )

    expect(valid.valid).toBe(true)
  })

  test('ne peut pas ajouter une 2ème demande en construction à une démarche', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2024-01-01'))
    expect(
      titreDemarcheUpdatedEtatValidate(
        machineInfo,
        [{ id: demarcheId }],
        {
          typeId: 'mfr',
          statutId: 'fai',
          isBrouillon: ETAPE_IS_BROUILLON,
          date: caminoDateValidator.parse('2024-01-02'),
          concurrence: { amIFirst: true },
          demarcheIdsConsentement: [],
          hasTitreFrom: true,
        },
        [
          {
            id: etapeIdValidator.parse('1'),
            typeId: 'mfr',
            statutId: 'fai',
            isBrouillon: ETAPE_IS_BROUILLON,
            date: caminoDateValidator.parse('2024-01-01'),
            ordre: 1,
            concurrence: { amIFirst: true },
            hasTitreFrom: true,
            demarcheIdsConsentement: [],
          },
        ]
      )
    ).toMatchInlineSnapshot(`
      {
        "errors": [
          "les étapes de la démarche machine AncienLogigrammeOctroiAXM ne sont pas valides",
        ],
        "valid": false,
      }
    `)
  })

  test('ne peut pas ajouter une étape de type inconnu sur une machine', () => {
    const demarcheId = newDemarcheId()
    const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2021-01-01'))
    expect(
      titreDemarcheUpdatedEtatValidate(
        machineInfo,
        [{ id: demarcheId }],
        {
          typeId: 'aaa' as EtapeTypeId,
          date: toCaminoDate('2022-01-01'),
          statutId: 'fai',
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          communes: null,
          contenu: null,
          surface: null,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
        [
          {
            id: newEtapeId('1'),
            typeId: EtapesTypesEtapesStatuts.demande.FAIT.etapeTypeId,
            statutId: EtapesTypesEtapesStatuts.demande.FAIT.etapeStatutId,
            isBrouillon: ETAPE_IS_BROUILLON,
            date: toCaminoDate('2021-01-01'),
            communes: null,
            contenu: null,
            ordre: 1,
            surface: null,
            concurrence: { amIFirst: true },
            hasTitreFrom: true,
            demarcheIdsConsentement: [],
          },
        ]
      )
    ).toMatchInlineSnapshot(`
      {
        "errors": [
          "les étapes de la démarche machine AncienLogigrammeOctroiAXM ne sont pas valides",
        ],
        "valid": false,
      }
    `)
  })
})

describe('getPossiblesEtapesTypes', () => {
  test("bug prod edition d'une étape quand une étape de même type est en brouillon", () => {
    const rcoId = newEtapeId('rcoId')
    const etapes: Pick<ITitreEtape, 'typeId' | 'date' | 'isBrouillon' | 'id' | 'ordre' | 'statutId' | 'communes'>[] = [
      { typeId: 'rco', date: toCaminoDate('2025-04-10'), isBrouillon: ETAPE_IS_BROUILLON, id: newEtapeId(), ordre: 18, statutId: 'fai', communes: [] },
      { typeId: 'men', date: toCaminoDate('2018-12-28'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 3, statutId: 'fai', communes: [] },
      { typeId: 'spp', date: toCaminoDate('2019-02-12'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 4, statutId: 'fai', communes: [] },
      { typeId: 'mco', date: toCaminoDate('2019-04-29'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 5, statutId: 'fai', communes: [] },
      {
        typeId: 'mfr',
        date: toCaminoDate('2018-12-20'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId(),
        ordre: 1,
        statutId: 'fai',
        communes: [{ id: toCommuneId('67001') }],
      },
      {
        typeId: 'mod',
        date: toCaminoDate('2018-12-21'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId(),
        ordre: 2,
        statutId: 'fai',
        communes: [{ id: toCommuneId('67001') }],
      },
      { typeId: 'rco', date: toCaminoDate('2019-06-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: rcoId, ordre: 6, statutId: 'fai', communes: [] },
      { typeId: 'mcr', date: toCaminoDate('2019-07-10'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 7, statutId: 'fav', communes: [] },
      { typeId: 'asc', date: toCaminoDate('2019-07-17'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 8, statutId: 'fai', communes: [] },
      { typeId: 'adc', date: toCaminoDate('2019-07-17'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 9, statutId: 'fai', communes: [] },
      { typeId: 'anf', date: toCaminoDate('2019-07-19'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 10, statutId: 'ter', communes: [] },
      { typeId: 'apd', date: toCaminoDate('2020-01-13'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 11, statutId: 'fav', communes: [] },
      { typeId: 'app', date: toCaminoDate('2020-09-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 12, statutId: 'fav', communes: [] },
      { typeId: 'ppu', date: toCaminoDate('2020-10-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 13, statutId: 'ter', communes: [] },
      { typeId: 'rco', date: toCaminoDate('2023-09-25'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 14, statutId: 'fai', communes: [] },
      { typeId: 'ppu', date: toCaminoDate('2024-01-15'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 15, statutId: 'ter', communes: [] },
      { typeId: 'apd', date: toCaminoDate('2024-03-19'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 16, statutId: 'fre', communes: [] },
      { typeId: 'app', date: toCaminoDate('2024-04-08'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 17, statutId: 'def', communes: [] },
    ]
    const demarcheId = newDemarcheId()
    const machineInfo = new ApiMachineInfo(
      MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2019-06-06'))
    )
    const tested = getPossiblesEtapesTypes(
      machineInfo,

      ETAPES_TYPES.receptionDeComplements,
      rcoId,
      toCaminoDate('2019-06-06'),
      etapes.map(etape => ({ ...etape, demarcheIdsConsentement: [] }))
    )

    expect(tested.rco).toMatchInlineSnapshot(`
      {
        "etapeStatutIds": [
          "fai",
        ],
        "mainStep": false,
      }
    `)
  })

  test('peut déplacer le Rapport et avis de la DREAL avant la Consultation du public pour les Octrois de Permis exclusif de recherches ', () => {
    const apdId = newEtapeId('apiId')
    const etapes: TitreEtapeForMachine[] = [
      {
        typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL,
        date: toCaminoDate('2024-05-29'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: apdId,
        ordre: 8,
        statutId: 'fav',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives,
        date: toCaminoDate('2023-12-22'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('avisDesServicesEtCommissionsConsultatives'),
        ordre: 6,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.consultationDuPublic,
        date: toCaminoDate('2024-05-28'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('ppuID'),
        ordre: 7,
        statutId: 'ter',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.demande,
        date: toCaminoDate('2023-02-28'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('demandeId'),
        ordre: 1,
        statutId: 'fai',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF,
        date: toCaminoDate('2023-09-01'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('anf'),
        ordre: 5,
        statutId: 'ter',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.enregistrementDeLaDemande,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('men'),
        ordre: 2,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.saisineDuPrefet,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('spp'),
        ordre: 3,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.recevabiliteDeLaDemande,
        date: toCaminoDate('2023-06-23'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('mcr'),
        ordre: 4,
        statutId: 'fav',
        communes: [],
        demarcheIdsConsentement: [],
      },
    ]

    expect(
      getPossiblesEtapesTypes(
        new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')),
        ETAPES_TYPES.rapportEtAvisDeLaDREAL,
        apdId,
        toCaminoDate('2024-05-22'),
        etapes
      )
    ).toMatchInlineSnapshot(`
      {
        "apd": {
          "etapeStatutIds": [
            "fav",
            "def",
            "fre",
            "dre",
          ],
          "mainStep": true,
        },
        "mec": {
          "etapeStatutIds": [
            "fai",
          ],
          "mainStep": false,
        },
        "mif": {
          "etapeStatutIds": [
            "fai",
          ],
          "mainStep": false,
        },
        "mod": {
          "etapeStatutIds": [
            "fai",
          ],
          "mainStep": false,
        },
        "rif": {
          "etapeStatutIds": [
            "fai",
          ],
          "mainStep": false,
        },
      }
    `)
  })

  test("peut déplacer la saisineDuPrefet qui est le même jour que d'autres", () => {
    const sppId = newEtapeId('spp')
    const etapes: TitreEtapeForMachine[] = [
      {
        typeId: ETAPES_TYPES.demande,
        date: toCaminoDate('2023-02-28'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('demandeId'),
        ordre: 1,
        statutId: 'fai',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('anf'),
        ordre: 5,
        statutId: 'ter',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.enregistrementDeLaDemande,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('men'),
        ordre: 2,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.saisineDuPrefet,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: sppId,
        ordre: 3,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.recevabiliteDeLaDemande,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('mcr'),
        ordre: 4,
        statutId: 'fav',
        communes: [],
        demarcheIdsConsentement: [],
      },
    ]

    expect(
      getPossiblesEtapesTypes(
        new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')),
        ETAPES_TYPES.saisineDuPrefet,
        sppId,
        toCaminoDate('2023-05-03'),
        etapes
      )
    ).toMatchInlineSnapshot(`
      {
        "spp": {
          "etapeStatutIds": [
            "fai",
          ],
          "mainStep": true,
        },
      }
    `)
  })

  test("peut déplacer l'enregistrement de la demande le même jour", () => {
    const menId = newEtapeId('menId')
    const etapes: TitreEtapeForMachine[] = [
      {
        typeId: ETAPES_TYPES.demande,
        date: toCaminoDate('2023-02-28'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('demandeId'),
        ordre: 1,
        statutId: 'fai',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('anf'),
        ordre: 5,
        statutId: 'ter',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.enregistrementDeLaDemande,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: menId,
        ordre: 2,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.saisineDuPrefet,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('spp'),
        ordre: 3,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.recevabiliteDeLaDemande,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('mcr'),
        ordre: 4,
        statutId: 'fav',
        communes: [],
        demarcheIdsConsentement: [],
      },
    ]

    expect(
      getPossiblesEtapesTypes(
        new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')),
        ETAPES_TYPES.enregistrementDeLaDemande,
        menId,
        toCaminoDate('2023-05-03'),
        etapes
      )
    ).toMatchInlineSnapshot(`
      {
        "men": {
          "etapeStatutIds": [
            "fai",
          ],
          "mainStep": true,
        },
      }
    `)
  })

  test("ne peut pas déplacer l'enregistrement de la demande après les autres étapes", () => {
    const menId = newEtapeId('menId')
    const etapes: TitreEtapeForMachine[] = [
      {
        typeId: ETAPES_TYPES.demande,
        date: toCaminoDate('2023-02-28'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('demandeId'),
        ordre: 1,
        statutId: 'fai',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('anf'),
        ordre: 5,
        statutId: 'ter',
        communes: [{ id: toCommuneId('64012') }],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.enregistrementDeLaDemande,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: menId,
        ordre: 2,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.saisineDuPrefet,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('spp'),
        ordre: 3,
        statutId: 'fai',
        communes: [],
        demarcheIdsConsentement: [],
      },
      {
        typeId: ETAPES_TYPES.recevabiliteDeLaDemande,
        date: toCaminoDate('2023-05-03'),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        id: newEtapeId('mcr'),
        ordre: 4,
        statutId: 'fav',
        communes: [],
        demarcheIdsConsentement: [],
      },
    ]

    expect(
      getPossiblesEtapesTypes(
        new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')),
        ETAPES_TYPES.enregistrementDeLaDemande,
        menId,
        toCaminoDate('2023-06-01'),
        etapes
      )
    ).toMatchInlineSnapshot(`
      {}
    `)
  })

  test('peut créer une étape sur une procédure spécifique vide', () => {
    expect(
      getPossiblesEtapesTypes(
        new ApiMachineInfo(throwableMachineInfoForTestsOnly('cxm', DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'ProcedureSpecifique')),
        undefined,
        undefined,
        toCaminoDate('4000-02-01'),
        []
      )
    ).toMatchInlineSnapshot(`
      {
        "mfr": {
          "etapeStatutIds": [
            "fai",
          ],
          "mainStep": true,
        },
      }
    `)
  })
  const etapes: TitreEtapeForMachine[] = [
    {
      id: newEtapeId('etapeId16'),
      typeId: 'sco',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 16,
      date: toCaminoDate('2020-08-17'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: { arm: { mecanise: true } },
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId1'),
      typeId: 'mfr',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 1,
      date: toCaminoDate('2019-09-19'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: { arm: { mecanise: true, franchissements: 19 } },
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId5'),
      typeId: 'mcp',
      statutId: 'com',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 5,
      date: toCaminoDate('2019-11-27'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId10'),
      typeId: 'asc',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 10,
      date: toCaminoDate('2019-12-06'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId14'),
      typeId: 'pfc',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 14,
      date: toCaminoDate('2020-05-21'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId8'),
      typeId: 'mcr',
      statutId: 'fav',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 8,
      date: toCaminoDate('2019-12-05'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId4'),
      typeId: 'pfd',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 4,
      date: toCaminoDate('2019-11-20'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId15'),
      typeId: 'vfc',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 15,
      date: toCaminoDate('2020-05-22'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId13'),
      typeId: 'mnb',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 13,
      date: toCaminoDate('2020-05-18'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId12'),
      typeId: 'aca',
      statutId: 'fav',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 12,
      date: toCaminoDate('2020-05-13'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId6'),
      typeId: 'rde',
      statutId: 'fav',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 6,
      date: toCaminoDate('2019-12-03'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      communes: [],
      surface: null,
      contenu: { arm: { franchissements: 19 } },
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId2'),
      typeId: 'men',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 2,
      date: toCaminoDate('2019-09-20'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId7'),
      typeId: 'vfd',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 7,
      date: toCaminoDate('2019-12-04'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId11'),
      typeId: 'sca',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 11,
      date: toCaminoDate('2020-05-04'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId3'),
      typeId: 'dae',
      statutId: 'exe',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 3,
      date: toCaminoDate('2019-10-11'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
    {
      id: newEtapeId('etapeId17'),
      typeId: 'aco',
      statutId: 'fai',
      concurrence: 'non-applicable',
      hasTitreFrom: 'non-applicable',
      isBrouillon: ETAPE_IS_NOT_BROUILLON,
      ordre: 17,
      date: toCaminoDate('2022-05-05'),
      dateFin: null,
      dateDebut: null,
      duree: null,
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
  ]

  const apiMachineInfoArmOct = new ApiMachineInfo(
    throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiARM')
  )
  test('modifie une étape existante', () => {
    const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, etapeIdValidator.parse('etapeId3'), toCaminoDate('2019-10-11'), etapes)
    expect(Object.keys(tested)).toHaveLength(1)
    expect(tested.dae).toMatchInlineSnapshot(`
      {
        "etapeStatutIds": [
          "exe",
        ],
        "mainStep": true,
      }
    `)
  })

  test.each(etapes)("modifie l'étape %# existante à la même date devrait permettre de recréer la même étape", etape => {
    const etapesTypesPossibles = getPossiblesEtapesTypes(apiMachineInfoArmOct, etape.typeId, etape.id, etape.date, etapes)
    expect(Object.keys(etapesTypesPossibles).length, `pas d'étapes possibles à l'étape ${JSON.stringify(etape)}. Devrait contenir AU MOINS la même étape`).toBeGreaterThan(0)
    expect(etapesTypesPossibles[etape.typeId]).toHaveProperty('etapeStatutIds')
  })

  test('ajoute une nouvelle étape à la fin', () => {
    const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2022-05-06'), etapes)
    expect(Object.keys(tested)).toHaveLength(1)
    expect(tested.mnv).toMatchInlineSnapshot(`
      {
        "etapeStatutIds": [
          "fai",
        ],
        "mainStep": false,
      }
    `)
  })

  test('ajoute une nouvelle étape en plein milieu', () => {
    const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2019-12-04'), etapes)
    expect(Object.keys(tested).toSorted()).toStrictEqual(['mca', 'mim', 'mod'])
  })

  test('peut faire une dae, une rde et pfd AVANT la mfr', () => {
    const etapes: TitreEtapeForMachine[] = [
      {
        id: newEtapeId('idMfr'),
        ordre: 1,
        typeId: 'mfr',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-05-16'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        contenu: { arm: { mecanise: true, franchissements: 2 } },
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idMdp'),
        ordre: 2,
        typeId: 'men',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-05-17'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
    ]

    const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2019-12-04'), etapes)
    expect(Object.keys(tested).toSorted()).toStrictEqual(['dae', 'pfd', 'rde'])
  })

  test('peut faire que une pfd AVANT la mfr non mecanisee', () => {
    const etapes: TitreEtapeForMachine[] = [
      {
        id: newEtapeId('idMfr'),
        ordre: 1,
        typeId: 'mfr',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-05-16'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        contenu: { arm: { mecanise: false } },
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idMdp'),
        ordre: 2,
        typeId: 'men',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-05-17'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
    ]

    const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2019-12-04'), etapes)
    expect(Object.keys(tested)).toStrictEqual(['pfd'])
  })

  test('peut faire refuser une rde après une demande mécanisée', () => {
    console.warn = vi.fn()
    const etapes: TitreEtapeForMachine[] = [
      {
        id: newEtapeId('idMfr'),
        date: toCaminoDate('2021-11-02'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'mfr',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        contenu: {
          arm: {
            mecanise: true,
            franchissements: 9,
          },
        },
        ordre: 3,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idrcm'),
        date: toCaminoDate('2021-11-17'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'rcm',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        contenu: {
          arm: {
            mecanise: true,
            franchissements: 9,
          },
        },
        ordre: 7,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idMcp'),
        date: toCaminoDate('2021-11-05'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'mcp',
        statutId: 'inc',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ordre: 5,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idmcp'),
        date: toCaminoDate('2021-11-17'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'mcp',
        statutId: 'com',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ordre: 8,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('iddae'),
        date: toCaminoDate('2021-10-15'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'dae',
        statutId: 'exe',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,

        ordre: 1,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idmcr'),
        date: toCaminoDate('2021-11-22'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'mcr',
        statutId: 'fav',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        contenu: null,
        ordre: 10,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idmcb'),
        date: toCaminoDate('2021-12-09'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'mcb',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,

        ordre: 13,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idexp'),
        date: toCaminoDate('2021-11-30'),
        typeId: 'exp',
        dateFin: null,
        dateDebut: null,
        duree: null,
        statutId: 'fav',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ordre: 12,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idvfd'),
        date: toCaminoDate('2021-11-19'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'vfd',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ordre: 9,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idpfd'),
        date: toCaminoDate('2021-10-26'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'pfd',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ordre: 2,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idmen'),
        date: toCaminoDate('2021-11-02'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'men',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ordre: 4,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('idmcm'),
        date: toCaminoDate('2021-11-05'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        typeId: 'mcm',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ordre: 6,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
    ]

    const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2022-07-01'), etapes)
    expect(Object.keys(tested).toSorted()).toStrictEqual(['asc', 'css', 'des', 'mcb', 'mod', 'rcb', 'rde'])
    vi.resetAllMocks()
  })
  test('peut faire une completude (mcp) le même jour que le dépôt (men) de la demande', () => {
    const etapes: TitreEtapeForMachine[] = [
      {
        id: newEtapeId('id3'),
        typeId: 'mfr',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-06-23'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        contenu: {
          arm: {
            mecanise: true,
            franchissements: 4,
          },
        },
        ordre: 3,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('id1'),
        typeId: 'dae',
        statutId: 'exe',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2021-06-22'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        ordre: 1,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('id4'),

        typeId: 'men',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2022-07-01'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        ordre: 4,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
      {
        id: newEtapeId('id2'),

        typeId: 'pfd',
        statutId: 'fai',
        concurrence: 'non-applicable',
        hasTitreFrom: 'non-applicable',
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: toCaminoDate('2021-07-05'),
        dateFin: null,
        dateDebut: null,
        duree: null,
        ordre: 2,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
    ]

    const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2022-07-01'), etapes)
    expect(Object.keys(tested).toSorted()).toStrictEqual(['css', 'des', 'mcb', 'mcp', 'mod', 'rde'])
  })

  const commonEtape: Pick<TitreEtapeForMachine, 'hasTitreFrom' | 'concurrence' | 'contenu' | 'communes' | 'surface' | 'demarcheIdsConsentement' | 'hasTitreFrom'> = {
    hasTitreFrom: 'non-applicable',
    concurrence: 'non-applicable',
    contenu: {},
    communes: [],
    surface: null,
    demarcheIdsConsentement: [],
  } as const
  const apiMachineInfoSpecifique = new ApiMachineInfo(
    throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'ProcedureSpecifique')
  )
  test("peut éditer une demande sur la procédure spécifique d'une démarche bien avancée", () => {
    const demandeId = newEtapeId('idMfr')
    const dateDemande = toCaminoDate('2024-12-01')
    const etapes: TitreEtapeForMachine[] = [
      {
        id: demandeId,
        ordre: 1,
        typeId: ETAPES_TYPES.demande,
        statutId: ETAPES_STATUTS.FAIT,
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        date: dateDemande,
        dateFin: null,
        dateDebut: null,
        duree: null,
        ...commonEtape,
      },
      {
        id: newEtapeId('idEnregistrement'),
        ordre: 2,
        typeId: ETAPES_TYPES.enregistrementDeLaDemande,
        statutId: ETAPES_STATUTS.FAIT,
        date: dateAddDays(dateDemande, 1),
        dateFin: null,
        dateDebut: null,
        duree: null,
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ...commonEtape,
      },
      {
        id: newEtapeId('idRecevabilite'),
        ordre: 3,
        typeId: ETAPES_TYPES.recevabiliteDeLaDemande,
        statutId: ETAPES_STATUTS.FAVORABLE,
        date: dateAddDays(dateDemande, 2),
        dateFin: null,
        dateDebut: null,
        duree: null,
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ...commonEtape,
        hasTitreFrom: false,
      },
      {
        id: newEtapeId('idConsentement'),
        ordre: 4,
        typeId: ETAPES_TYPES.demandeDeConsentement,
        statutId: ETAPES_STATUTS.FAIT,
        date: dateAddDays(dateDemande, 3),
        dateFin: null,
        dateDebut: null,
        duree: null,
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ...commonEtape,
      },
    ]

    const tested = getPossiblesEtapesTypes(apiMachineInfoSpecifique, ETAPES_TYPES.demande, demandeId, dateDemande, etapes)

    expect(Object.keys(tested)).toStrictEqual([ETAPES_TYPES.demande])
  })
})
