/** Ligne de collection supprimable (contact / adresse / RIB). */
export interface DeletableRow {
    id?: number | null
}

/**
 * Indique si le bloc d'index `index` peut afficher sa poubelle (ERP-172).
 *
 * Regle metier : on ne peut supprimer un bloc QUE s'il reste au moins un AUTRE
 * bloc deja enregistre (`id` non null, donc persiste en base). Consequences :
 *  - tant que rien n'est enregistre -> aucune poubelle (pas de suppression d'un
 *    simple brouillon saisi mais pas valide) ;
 *  - on peut jeter un brouillon non enregistre s'il reste un bloc enregistre ;
 *  - on ne peut jamais supprimer son dernier bloc enregistre.
 */
export function isRowRemovable<T extends DeletableRow>(rows: T[], index: number): boolean {
    return rows.some((row, i) => i !== index && row.id != null)
}

/** Options de {@link removeCollectionRow}. */
export interface RemoveCollectionRowOptions<T extends DeletableRow> {
    /** Tableau reactif des brouillons (passer le `.value` de la ref). */
    rows: T[]
    /** Tableau reactif des erreurs par ligne, aligne sur l'index (passer le `.value`). */
    errors: Record<string, string>[]
    /** Index de la ligne a retirer. */
    index: number
    /** Endpoint de la sous-ressource SANS id (ex: '/client_contacts'). */
    endpoint: string
    /** Suppression serveur : DOIT rejeter en cas d'echec (ex: url => api.delete(url, {}, { toast: false })). */
    deleteRow: (url: string) => Promise<unknown>
    /** Fabrique d'un bloc vide pour garder au moins un bloc visible apres retrait. */
    makeEmpty: () => T
    /** Remontee d'erreur 409/422 mappee proprement (message back, pas de toast fourre-tout). */
    onError: (error: unknown) => void
}

/**
 * Retire une ligne de collection (contact / adresse / RIB) sur les ecrans de
 * MODIFICATION, avec DELETE immediat de la sous-ressource (ERP-172). Comportement
 * aligne sur les 3 modules (Client / Fournisseur / Prestataire) :
 *
 *  - Bloc jamais persiste (`id` null) : simple retrait local, aucun appel reseau.
 *  - Bloc existant (`id` non null) : DELETE `/endpoint/{id}` AVANT le retrait du
 *    tableau. On ne retire le bloc QUE si le serveur a confirme — sinon le bloc
 *    reste affiche et l'erreur est remontee via `onError` (ex. dernier RIB d'une
 *    LCR -> 409 back, RG-x.08).
 *
 * Etat purement local : `rows`/`errors` sont les `.value` des refs (proxies
 * reactifs), le `splice` declenche donc la reactivite.
 *
 * @returns `true` si la ligne a ete retiree (suppression confirmee ou bloc local),
 *          `false` si la suppression serveur a echoue (bloc conserve).
 */
export async function removeCollectionRow<T extends DeletableRow>(
    options: RemoveCollectionRowOptions<T>,
): Promise<boolean> {
    const { rows, errors, index, endpoint, deleteRow, makeEmpty, onError } = options
    const removed = rows[index]

    // Bloc existant : suppression serveur d'abord, retrait local seulement si OK.
    if (removed?.id != null) {
        try {
            await deleteRow(`${endpoint}/${removed.id}`)
        }
        catch (error) {
            onError(error)
            return false
        }
    }

    rows.splice(index, 1)
    errors.splice(index, 1)
    // Garde au moins un bloc visible (cf. amorce a l'hydratation).
    if (rows.length === 0) {
        rows.push(makeEmpty())
    }
    return true
}
