import { titreEtapeUpdate } from '../../database/queries/titres-etapes'
import { titreEtapesSortAscByDate } from '../utils/titre-etapes-sort'
import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes'
import { TitreTypeId } from 'camino-common/src/static/titresTypes'
import { getDemarches } from './titres-etapes-heritage-contenu-update.queries'
import { UserNotNull } from 'camino-common/src/roles'
import { DemarcheId } from 'camino-common/src/demarche'
import { Pool } from 'pg'
import { TitreId } from 'camino-common/src/validators/titres'
import { TitreEtapeForMachine, titreEtapeForMachineValidator } from '../rules-demarches/machine-common'
import { isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools'
import { callAndExit } from '../../tools/fp-tools'
import { MachineInfo } from 'camino-common/src/machines'
import { CaminoMachineId } from 'camino-common/src/validators/machine'

export const titresEtapesOrdreUpdate = async (pool: Pool, user: UserNotNull, demarcheId?: DemarcheId): Promise<string[]> => {
  console.info()
  console.info('ordre des étapes…')

  const titresDemarches = await callAndExit(getDemarches(pool, demarcheId))

  return titresEtapesOrdreUpdateVisibleForTesting(user, titresDemarches)
}

export const titresEtapesOrdreUpdateVisibleForTesting = async (
  user: UserNotNull,
  titresDemarches: {
    [key: DemarcheId]: {
      etapes: TitreEtapeForMachine[]
      id: DemarcheId
      typeId: DemarcheTypeId
      titreTypeId: TitreTypeId
      titreId: TitreId
      machineId: CaminoMachineId | null
    }
  }
): Promise<string[]> => {
  const titresEtapesIdsUpdated: string[] = []

  for (const titreDemarche of Object.values(titresDemarches)) {
    if (isNotNullNorUndefinedNorEmpty(titreDemarche.etapes)) {
      const etapesMachine = titreDemarche.etapes.map(etape => titreEtapeForMachineValidator.parse(etape))

      const machineInfo = MachineInfo.withMachineId(titreDemarche.titreTypeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId)
      if (!machineInfo.valid) {
        throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`)
      }

      const etapes = titreEtapesSortAscByDate(etapesMachine, machineInfo.value)
      for (let index = 0; index < etapes.length; index++) {
        const titreEtape = etapes[index]
        if (titreEtape.ordre !== index + 1) {
          await titreEtapeUpdate(titreEtape.id, { ordre: index + 1 }, user, titreDemarche.titreId)

          console.info('titre / démarche / étape : ordre (mise à jour) ->', `${titreEtape.id} : ${index + 1}`)

          titresEtapesIdsUpdated.push(titreEtape.id)
        }
      }
    }
  }

  return titresEtapesIdsUpdated
}
