import { ITitreDemarche, ITitreEtape } from '../../types'
import { titreDemarcheStatutIdFind } from '../rules/titre-demarche-statut-id-find'
import { TitreTypeId } from 'camino-common/src/static/titresTypes'
import { titrePhasesFind } from '../rules/titre-phases-find'
import { CaminoDate } from 'camino-common/src/date'
import { titreEtapeForMachineValidator } from '../rules-demarches/machine-common'
import { isNotNullNorUndefinedNorEmpty, isNullOrUndefinedOrEmpty } from 'camino-common/src/typescript-tools'
import { MachineInfo } from 'camino-common/src/machines'

/**
 * Filtre les étapes antérieures à une date
 */
const titreEtapesFilter = (titreEtapes: ITitreEtape[], date: string) => titreEtapes.filter(titreEtape => titreEtape.date <= date)

/**
 * Reconstruit les démarches et étapes antérieures à une date
 * et recalcule le statut des démarches en fonction des étapes
 */
export const titreDemarchesEtapesRebuild = (date: CaminoDate, titreDemarches: ITitreDemarche[], titreTypeId: TitreTypeId): (Omit<ITitreDemarche, 'etapes'> & { etapes: ITitreEtape[] })[] => {
  const titreDemarchesRebuilt: ReturnType<typeof titreDemarchesEtapesRebuild> = []
  for (const td of titreDemarches) {
    if (isNullOrUndefinedOrEmpty(td.etapes)) {
      continue
    }

    const titreEtapesFiltered = titreEtapesFilter(td.etapes, date)

    if (isNotNullNorUndefinedNorEmpty(titreEtapesFiltered)) {
      const titreDemarche = { ...td, etapes: titreEtapesFiltered }

      // TODO 2025-03-26 c'est hyper dangereux d'utiliser zod pour stripper les données à l'intérieur de notre code, ça doit être utilisé uniquement aux abords des API et de la BDD
      const etapes = titreDemarche.etapes.map(etape => titreEtapeForMachineValidator.parse(etape))
      const machineInfo = MachineInfo.withMachineId(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}`)
      }

      titreDemarche.statutId = titreDemarcheStatutIdFind(machineInfo.value, etapes)

      titreDemarchesRebuilt.push(titreDemarche)
    }
  }

  const phases = titrePhasesFind(titreDemarchesRebuilt, titreTypeId)

  return titreDemarchesRebuilt.map(demarche => {
    const phase = phases[demarche.id]
    if (!phase) {
      delete demarche.demarcheDateDebut
      delete demarche.demarcheDateFin
    } else {
      demarche.demarcheDateDebut = phase.dateDebut
      demarche.demarcheDateFin = phase.dateFin
    }

    return demarche
  })
}
