# TableDataDomainModel.kt

    /*
     * The MIT License
     *
     * Original work sponsored and donated by The Danish Health Data Authority (http://www.sundhedsdatastyrelsen.dk)
     *
     * Copyright (C) 2025 The Danish Health Data Authority (http://www.sundhedsdatastyrelsen.dk)
     *
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy of
     * this software and associated documentation files (the "Software"), to deal in
     * the Software without restriction, including without limitation the rights to
     * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     * of the Software, and to permit persons to whom the Software is furnished to do
     * so, subject to the following conditions:
     *
     *
     * The above copyright notice and this permission notice shall be included in all
     * copies or substantial portions of the Software.
     *
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     * SOFTWARE.
     */
    package dk.nsp.mingraviditet.core.data.domain.tableData

    import android.os.Parcelable
    import dk.nsp.mingraviditet.core.model.data.TableData
    import dk.nsp.mingraviditet.core.model.data.TableDataType
    import dk.nsp.mingraviditet.core.model.data.TableDataTypeAction
    import dk.nsp.mingraviditet.core.network.measurements.model.DataItemDTO
    import dk.nsp.mingraviditet.core.network.measurements.model.TablesDataDTO
    import kotlinx.parcelize.Parcelize
    import java.time.LocalDate
    import java.time.format.DateTimeFormatter

    data class TableDataDomainModel(
        val tabs: List<Tab>,
    )

    @Parcelize
    data class Tab(
        val tabName: String,
        val tables: List<Table>,
        val date: LocalDate?,
    ) : Parcelable

    @Parcelize
    data class Table(
        val name: String,
        val columns: List<Column> = emptyList(),
    ) : Parcelable

    @Parcelize
    data class Column(
        val date: LocalDate?,
        val cells: List<Cell> = emptyList(),
    ) : Parcelable

    @Parcelize
    data class Cell(
        val name: String,
        val valueAndUnit: String,
        val unit: String?,
        val info: String?,
        val chart: Map<String, String>?,
    ) : Parcelable

    fun TablesDataDTO.toDomain(): TableDataDomainModel {
        return TableDataDomainModel(
            tabs = this.data.map { dataItemDTO ->
                dataItemDTO.toDomain()
            },
        )
    }

    fun DataItemDTO.toDomain(): Tab = Tab(
        date = this.date,
        tabName = this.name ?: "-",
        tables = this.tables.map { tableDTO ->
            Table(
                name = tableDTO.name,
                columns = tableDTO.columns.map { columnDTO ->
                    Column(
                        date = columnDTO.date,
                        cells = columnDTO.cells.map { cellDTO ->
                            Cell(
                                name = cellDTO.name,
                                unit = cellDTO.unit,
                                info = cellDTO.info,
                                valueAndUnit = cellDTO.valueAndUnit ?: "-",
                                chart = cellDTO.chart?.mapValues { it.value },
                            )
                        },
                    )
                },
            )
        },
    )

    private fun Column.toTableData(): List<TableData> {
        if (cells.isEmpty()) return emptyList()

        val dateString = this.date?.tableDate()

        return cells.map { cell ->
            val cellValue: String = cell.valueAndUnit

            val typeAction: TableDataTypeAction? = getTypeAction(cell)

            TableData(
                date = dateString,
                value = cellValue,
                type = TableDataType(
                    name = cell.name,
                    action = typeAction,
                ),
            )
        }
    }

    fun LocalDate.tableDate(): String? = this.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"))

    fun getTypeAction(cell: Cell): TableDataTypeAction? = when {
        // TODO: Chart data is not implemented yet, as it is currently out of scope.
        !cell.chart.isNullOrEmpty() -> null

        !cell.info.isNullOrEmpty() -> TableDataTypeAction.INFO(
            description = cell.info,
            title = cell.name,
        )

        else -> null
    }

    private fun List<TableData>.applyDataTypeIfMissing(): List<TableData> {
        val groupedDataNames: List<String> =
            this.map { it.type.name }.distinct()
        val mapOfDataNamesAndActions: Map<String, TableDataTypeAction?> = groupedDataNames.associateWith { dataName ->
            this.firstOrNull { it.type.name == dataName && it.type.action != null }?.type?.action
        }

        return this.map { data ->
            val actionForDataType: TableDataTypeAction? =
                mapOfDataNamesAndActions[data.type.name]

            if (data.type.action != null || actionForDataType == null) {
                return@map data
            }
            data.copy(
                type = data.type.copy(
                    action = actionForDataType,
                ),
            )
        }
    }

    fun List<Column>.toTableData(): List<TableData> {
        val allData: List<TableData> = this.flatMap { it.toTableData() }
        return allData.applyDataTypeIfMissing()
    }