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, 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 { ArmOctMachine } from '../rules-demarches/arm/oct.machine'
import { TitreEtapeForMachine } from '../rules-demarches/machine-common'
import { communeIdValidator, toCommuneId } from 'camino-common/src/static/communes'
import { km2Validator } from 'camino-common/src/number'
import { ProcedureSpecifiqueMachine } from '../rules-demarches/procedure-specifique/procedure-specifique.machine'
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'

console.warn = vi.fn()

describe('titreDemarcheUpdatedEtatValidate', () => {
  test('ajoute une étape à une démarche vide', () => {
    const demarcheId = newDemarcheId()
    const valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'arm',
        demarches: [{ 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: [],
      },
      demarcheId,
      null
    )

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

  test('ajoute une étape à une démarche qui contient déjà une étape', () => {
    const demarcheId = newDemarcheId()
    const valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'arm',
        demarches: [{ 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: [],
      },
      demarcheId,

      [
        {
          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 valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'prm',
        demarches: [{ id: demarcheId }],
      },
      demande,
      demarcheId,
      [
        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 valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'arm',
        demarches: [{ 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: [],
      },
      demarcheId,

      [
        {
          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-04'),
          statutId: 'fai',
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          communes: null,
          contenu: null,
          ordre: 2,
          surface: null,
          concurrence: { amIFirst: true },
          hasTitreFrom: true,
          demarcheIdsConsentement: [],
        },
      ]
    )

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

  test('l’ajout d’une étape d’une démarche historique est valide', () => {
    const demarcheId = newDemarcheId()
    const valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'arm',
        demarches: [{ id: demarcheId }],
      },
      {
        typeId: 'mfr',
        isBrouillon: ETAPE_IS_BROUILLON,
        date: caminoDateValidator.parse('2000-02-02'),
        statutId: 'fai',
        concurrence: { amIFirst: true },
        demarcheIdsConsentement: [],
        hasTitreFrom: true,
      },
      demarcheId,

      [
        {
          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 valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'arm',
        demarches: [{ id: demarcheId }],
      },
      {
        typeId: 'mfr',
        isBrouillon: ETAPE_IS_BROUILLON,
        date: caminoDateValidator.parse('2000-01-01'),
        statutId: 'fai',
        concurrence: { amIFirst: true },
        demarcheIdsConsentement: [],
        hasTitreFrom: true,
      },
      demarcheId,
      []
    )

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

  test("retourne une erreur si la démarche en cours de modification n'existe pas", () => {
    const demarcheId = newDemarcheId()
    expect(
      titreDemarcheUpdatedEtatValidate(
        'oct',
        {
          typeId: 'arm',
          demarches: [{ id: newDemarcheId() }],
        },
        {
          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: [],
        },
        demarcheId,

        []
      )
    ).toMatchInlineSnapshot(`
      {
        "errors": [
          "le titre ne contient pas la démarche en cours de modification",
        ],
        "valid": false,
      }
    `)

    expect(
      titreDemarcheUpdatedEtatValidate(
        'oct',
        {
          typeId: 'arm',
          demarches: [{ id: demarcheId }],
        },
        {
          id: etapeIdValidator.parse('1'),
          typeId: ETAPES_TYPES.demande,
          date: caminoDateValidator.parse('2025-01-01'),
          concurrence: { amIFirst: true },
          hasTitreFrom: false,
          statutId: ETAPES_STATUTS.FAIT,
          isBrouillon: ETAPE_IS_NOT_BROUILLON,
          demarcheIdsConsentement: [],
          communes: [{ id: toCommuneId('97300') }],
          surface: km2Validator.parse(12),
        },
        demarcheId,

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

  test('supprime une étape', () => {
    const demarcheId = newDemarcheId()
    const valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'arm',
        demarches: [{ 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: [],
      },
      demarcheId,
      [
        {
          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 valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'arm',
        demarches: [
          {
            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: [],
      },
      demarcheId
    )

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

  test('ajoute une demande en construction à une démarche vide', () => {
    const demarcheId = newDemarcheId()
    const valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'axm',
        demarches: [{ 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),
      },
      demarcheId
    )

    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 valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'axm',
        demarches: [{ id: demarcheId }],
      },
      {
        typeId: 'mfr',
        statutId: 'fai',
        isBrouillon: ETAPE_IS_BROUILLON,
        date: caminoDateValidator.parse('2024-01-01'),
        concurrence: { amIFirst: true },
        demarcheIdsConsentement: [],
        hasTitreFrom: true,
      },
      demarcheId,

      [
        {
          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 valid = titreDemarcheUpdatedEtatValidate(
      'oct',
      {
        typeId: 'axm',
        demarches: [{ 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: [],
      },
      demarcheId,
      [
        {
          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()
    expect(
      titreDemarcheUpdatedEtatValidate(
        'oct',
        {
          typeId: 'axm',
          demarches: [{ id: demarcheId }],
        },
        {
          typeId: 'mfr',
          statutId: 'fai',
          isBrouillon: ETAPE_IS_BROUILLON,
          date: caminoDateValidator.parse('2024-01-02'),
          concurrence: { amIFirst: true },
          demarcheIdsConsentement: [],
          hasTitreFrom: true,
        },
        demarcheId,

        [
          {
            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 AXMOct ne sont pas valides",
        ],
        "valid": false,
      }
    `)
  })

  test('ne peut pas ajouter une étape de type inconnu sur une machine', () => {
    const demarcheId = newDemarcheId()
    expect(
      titreDemarcheUpdatedEtatValidate(
        'oct',
        {
          typeId: 'axm',
          demarches: [{ 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: [],
        },
        demarcheId,

        [
          {
            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 AXMOct ne sont pas valides",
        ],
        "valid": false,
      }
    `)
  })
})

describe('getPossiblesEtapesTypes', () => {
  test('peut créer une étape sur une procédure spécifique vide', () => {
    expect(getPossiblesEtapesTypes(new ProcedureSpecifiqueMachine('cxm', 'oct'), 'cxm', 'oct', 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'),
      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'),
      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'),
      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-04'),
      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-22'),
      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-04'),
      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'),
      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'),
      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'),
      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'),
      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-04'),
      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'),
      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'),
      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'),
      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'),
      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'),
      contenu: null,
      communes: [],
      surface: null,
      demarcheIdsConsentement: [],
    },
  ]

  const machine = new ArmOctMachine()
  test('modifie une étape existante', () => {
    const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, etapeIdValidator.parse('etapeId3'), toCaminoDate('2019-10-11'), etapes)
    expect(Object.keys(tested)).toHaveLength(1)
    expect(tested.dae).toMatchInlineSnapshot(`
      {
        "etapeStatutIds": [
          "exe",
        ],
        "mainStep": true,
      }
    `)
  })

  test('modifie une étape existante à la même date devrait permettre de recréer la même étape', () => {
    for (const etape of etapes) {
      const etapesTypesPossibles = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, etape.id, etape.date, etapes)
      if (Object.keys(etapesTypesPossibles).length === 0) {
        console.error(`pas d'étapes possibles à l'étape ${JSON.stringify(etape)}. Devrait contenir AU MOINS la même étape`)
      }
      expect(Object.keys(etapesTypesPossibles).length).toBeGreaterThan(0)
      expect(etapesTypesPossibles[etape.typeId]).toHaveProperty('etapeStatutIds')
    }
  })

  test('ajoute une nouvelle étape à la fin', () => {
    const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', 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(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2019-12-04'), etapes)
    expect(Object.keys(tested).toSorted()).toStrictEqual(['exp', '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'),
        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'),
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
    ]

    const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', 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'),
        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'),
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
    ]

    const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', 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'),
        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'),
        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'),
        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'),
        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'),
        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'),
        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'),
        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',
        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'),
        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'),
        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'),
        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'),
        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(machine, 'arm', 'oct', 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'),
        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'),
        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'),
        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'),
        ordre: 2,
        contenu: null,
        communes: [],
        surface: null,
        demarcheIdsConsentement: [],
      },
    ]

    const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', 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 procedureSpecifiqueMachine = new ProcedureSpecifiqueMachine('arm', 'oct')
  test("peut éditer une mfr 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,
        ...commonEtape,
      },
      {
        id: newEtapeId('idEnregistrement'),
        ordre: 2,
        typeId: ETAPES_TYPES.enregistrementDeLaDemande,
        statutId: ETAPES_STATUTS.FAIT,
        date: dateAddDays(dateDemande, 1),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ...commonEtape,
      },
      {
        id: newEtapeId('idRecevabilite'),
        ordre: 3,
        typeId: ETAPES_TYPES.recevabiliteDeLaDemande,
        statutId: ETAPES_STATUTS.FAVORABLE,
        date: dateAddDays(dateDemande, 2),
        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),
        isBrouillon: ETAPE_IS_NOT_BROUILLON,
        ...commonEtape,
      },
    ]

    const tested = getPossiblesEtapesTypes(
      procedureSpecifiqueMachine,
      TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX,
      DEMARCHES_TYPES_IDS.Octroi,
      ETAPES_TYPES.demande,
      demandeId,
      dateDemande,
      etapes
    )

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