using adas_core.Domain.Models.MongoModels;

namespace adas_core.Domain.Utils;

/// <summary>
/// Provides extension methods for the <see cref="DetailConfigExtension"/> type.
/// </summary>
/// <remarks>
/// This is a static utility class that cannot be instantiated and is intended to extend the functionality of <see cref="DetailConfigExtension"/> through extension method definitions.
/// </remarks>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
///      "The documentation states the class provides extension methods for 'DetailConfigExtension' itself, but by convention a class named 'DetailConfigExtension' is meant to extend another type (likely 'DetailConfig'), not itself." -->
public static class DetailConfigExtension
{
    // Método principal para iniciar la extracción
    /// <summary>
    /// Retrieves all unique observation names defined in the nurse rows of the specified <paramref name="config"/>.
    /// Returns an empty list when <see cref="CardDetailsConfig.NurseRows"/> is null.
    /// </summary>
    /// <param name="config">The <see cref="CardDetailsConfig"/> extension target whose nurse rows are inspected.</param>
    /// <returns>A <see cref="List{String}"/> containing the distinct observation names extracted from the nurse rows; an empty list when no nurse rows are defined.</returns>
    /// <!-- aidoc:v1 sig=1a41350 body=9520d6e -->
    public static List<string> GetAllObservationNames(this CardDetailsConfig config)
    {
        if (config.NurseRows == null) return [];

        // Se usa el método auxiliar para recorrer todas las RowDetailsConfig
        var observationNames = ExtractNamesFromRows(config.NurseRows)
            .Distinct() // Opcional: para nombres únicos
            .ToList();

        return observationNames;
    }

    // --- Auxiliar 1: Recorre la anidación de Filas (RowDetailsConfig) ---
    /// <summary>
    /// Recursively extracts names from a collection of <see cref="RowDetailsConfig"/> entries, traversing both the <see cref="RowDetailsConfig.Cells"/> and nested <see cref="RowDetailsConfig.Rows"/> of each row.
    /// </summary>
    /// <param name="rows">The list of <see cref="RowDetailsConfig"/> instances to process.</param>
    /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="string"/> containing all names collected from the cells and nested rows.</returns>
    /// <!-- aidoc:v1 sig=4148c6b body=c6277a5 -->
    private static IEnumerable<string> ExtractNamesFromRows(List<RowDetailsConfig> rows)
    {
        foreach (var row in rows)
        {
            // 1. EXTRAER de las CELDAS (Cells)
            if (row.Cells != null)
                // Usar SelectMany para aplanar los resultados del método recursivo de Celdas
                foreach (var name in row.Cells.SelectMany(ExtractNamesFromCells))
                    yield return name;

            // 2. EXTRAER de las FILAS ANIDADAS (Rows)
            if (row.Rows != null)
                // Llamada recursiva: Volver a este mismo método para procesar las filas anidadas
                foreach (var name in ExtractNamesFromRows(row.Rows))
                    yield return name;
        }
    }

    // --- Auxiliar 2: Recorre la anidación de Celdas (CellDetails) ---
    /// <summary>
    /// Recursively extracts every observation name from a <see cref="CellDetails"/>, yielding names from the current cell as well as from all its nested <see cref="CellDetails.Cells"/>. Null <see cref="CellDetails.ObservationName"/> and null <see cref="CellDetails.Cells"/> collections are safely skipped without yielding any elements.
    /// </summary>
    /// <param name="cell">The <see cref="CellDetails"/> whose observation names, including those of its descendant cells, should be collected.</param>
    /// <returns>A lazily evaluated <see cref="IEnumerable{T}"/> of <see cref="string"/> containing every observation name found in <paramref name="cell"/> and its nested cells.</returns>
    /// <!-- aidoc:v1 sig=a01fdc1 body=25dff85 -->
    private static IEnumerable<string> ExtractNamesFromCells(CellDetails cell)
    {
        // 1. EXTRAER nombres del nivel actual
        if (cell.ObservationName != null)
            foreach (var name in cell.ObservationName)
                yield return name;

        // 2. EXTRAER de las CELDAS ANIDADAS (Cells)
        if (cell.Cells != null)
            // Llamada recursiva: Volver a este mismo método para procesar las celdas anidadas
            foreach (var name in cell.Cells.SelectMany(ExtractNamesFromCells))
                yield return name;
    }
}