package de.arxsilex.maptools.converter.desktop

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Checkbox
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.arxsilex.maptools.converter.core.ContentSelection
import de.arxsilex.maptools.converter.core.ElevationOutputFormat
import de.arxsilex.maptools.converter.core.ExportSelection
import de.arxsilex.maptools.converter.core.MapFormatVersion
import de.arxsilex.maptools.converter.core.PoiSchemaVersion
import de.arxsilex.maptools.converter.desktop.generated.resources.Res
import de.arxsilex.maptools.converter.desktop.generated.resources.content_layers
import de.arxsilex.maptools.converter.desktop.generated.resources.export_data
import de.arxsilex.maptools.converter.desktop.generated.resources.map_source
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.painterResource

@Composable
internal fun ContentStep(
    contentSelection: ContentSelection,
    exportSelection: ExportSelection,
    rawPbfOutputAvailable: Boolean,
    hasMapSource: Boolean = true,
    hasPoiSource: Boolean = false,
    hasElevationSource: Boolean = false,
    hasPoiCompanion: Boolean = false,
    sourceMapVersion: Int? = null,
    onContentSelectionChange: (ContentSelection) -> Unit,
    onExportSelectionChange: (ExportSelection) -> Unit,
    onBack: () -> Unit,
    onNext: () -> Unit,
) {
    val strings = LocalAppStrings.current
    val isPoiOnlySource = !hasMapSource && hasPoiSource && !hasElevationSource
    val poiOutputAvailable = hasMapSource || hasPoiSource
    val poiUsesMapContent = !hasPoiSource
    val needsMapContent = hasMapSource && (
        exportSelection.mapsforgeMap || exportSelection.filteredPbf ||
            (exportSelection.mapsforgePoi && poiUsesMapContent)
        )
    ScrollableWorkflowPage(
        footer = {
            WorkflowFooter(
                status = when {
                    needsMapContent && !contentSelection.hasContent -> strings["content.status_content"]
                    !exportSelection.hasOutput -> strings["content.status_output"]
                    else -> strings["content.status_ready"]
                },
                onBack = onBack,
                onNext = onNext,
                nextLabel = strings["content.next_export"],
                nextEnabled = (!needsMapContent || contentSelection.hasContent) && exportSelection.hasOutput,
            )
        },
    ) {
        ScreenTitle(
            title = if (isPoiOnlySource) strings["content.poi_schema"] else strings["step.content"],
            description = if (isPoiOnlySource) {
                strings["content.poi_description"]
            } else {
                strings["content.description"]
            },
        )
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(20.dp),
        ) {
            CardContainer(modifier = Modifier.weight(1f)) {
                Text(strings["content.source_data"], style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.SemiBold)
                Spacer(Modifier.height(12.dp))
                if (!hasMapSource && hasPoiSource) {
                    Text(
                        strings["content.poi_only_hint"],
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                    Spacer(Modifier.height(12.dp))
                    Text(
                        strings["content.poi_conversion_hint"],
                        fontWeight = FontWeight.Medium,
                    )
                }
                if (hasElevationSource) {
                    if (!hasMapSource || hasPoiSource) Spacer(Modifier.height(12.dp))
                    Text(
                        strings["content.elevation_source_hint"],
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                }
                if (hasMapSource) {
                if (hasPoiCompanion) {
                    Text(
                        strings["content.companion_sources_hint"],
                        color = MaterialTheme.colorScheme.tertiary,
                        fontWeight = FontWeight.Medium,
                    )
                    Spacer(Modifier.height(12.dp))
                }
                sourceMapVersion?.let { version ->
                    Text(
                        strings("content.map_rebuild_hint", version),
                        color = MaterialTheme.colorScheme.tertiary,
                        fontWeight = FontWeight.Medium,
                    )
                    Spacer(Modifier.height(12.dp))
                }
                SelectionRow(strings["content.roads"], contentSelection.roads) {
                    onContentSelectionChange(contentSelection.copy(roads = it))
                }
                SelectionRow(strings["content.paths"], contentSelection.pathsAndTrails) {
                    onContentSelectionChange(contentSelection.copy(pathsAndTrails = it))
                }
                SelectionRow(strings["content.buildings"], contentSelection.buildings) {
                    onContentSelectionChange(contentSelection.copy(buildings = it))
                }
                SelectionRow(strings["content.land_water"], contentSelection.landAndWater) {
                    onContentSelectionChange(contentSelection.copy(landAndWater = it))
                }
                SelectionRow(strings["content.poi"], contentSelection.pointsOfInterest) {
                    onContentSelectionChange(contentSelection.copy(pointsOfInterest = it))
                    if (!it && exportSelection.mapsforgePoi && !hasPoiSource) {
                        onExportSelectionChange(exportSelection.copy(mapsforgePoi = false))
                    }
                }
                SelectionRow(strings["content.metadata"], contentSelection.sourceMetadata) {
                    onContentSelectionChange(contentSelection.copy(sourceMetadata = it))
                }
                }
            }
            CardContainer(modifier = Modifier.weight(1f)) {
                Text(strings["content.output_formats"], style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.SemiBold)
                Spacer(Modifier.height(12.dp))
                if (hasMapSource) OutputRow(
                    icon = Res.drawable.map_source,
                    title = strings["content.mapsforge_map"],
                    description = strings["content.map_description"],
                    checked = exportSelection.mapsforgeMap,
                ) { onExportSelectionChange(exportSelection.copy(mapsforgeMap = it)) }
                if (hasMapSource && exportSelection.mapsforgeMap) {
                    Spacer(Modifier.height(4.dp))
                    FormatVersionRow(
                        title = strings["content.map_v5"],
                        description = strings["content.map_v5_description"],
                        selected = exportSelection.mapFormatVersion == MapFormatVersion.V5,
                    ) {
                        onExportSelectionChange(exportSelection.copy(mapFormatVersion = MapFormatVersion.V5))
                    }
                    FormatVersionRow(
                        title = strings["content.map_v4"],
                        description = strings["content.map_v4_description"],
                        selected = exportSelection.mapFormatVersion == MapFormatVersion.V4,
                    ) {
                        onExportSelectionChange(exportSelection.copy(mapFormatVersion = MapFormatVersion.V4))
                    }
                }
                if (poiOutputAvailable) OutputRow(
                    icon = Res.drawable.content_layers,
                    title = strings["content.mapsforge_poi"],
                    description = if (hasPoiSource) {
                        strings["content.poi_companion_description"]
                    } else {
                        strings["content.poi_description_output"]
                    },
                    checked = exportSelection.mapsforgePoi && (contentSelection.pointsOfInterest || hasPoiSource),
                    enabled = contentSelection.pointsOfInterest || hasPoiSource,
                ) { onExportSelectionChange(exportSelection.copy(mapsforgePoi = it)) }
                if (poiOutputAvailable && exportSelection.mapsforgePoi &&
                    (contentSelection.pointsOfInterest || hasPoiSource)
                ) {
                    Spacer(Modifier.height(4.dp))
                    FormatVersionRow(
                        title = strings["content.poi_v3"],
                        description = strings["content.poi_v3_description"],
                        selected = exportSelection.poiSchemaVersion == PoiSchemaVersion.V3,
                    ) {
                        onExportSelectionChange(exportSelection.copy(poiSchemaVersion = PoiSchemaVersion.V3))
                    }
                    FormatVersionRow(
                        title = strings["content.poi_v4"],
                        description = strings["content.poi_v4_description"],
                        selected = exportSelection.poiSchemaVersion == PoiSchemaVersion.V4,
                    ) {
                        onExportSelectionChange(exportSelection.copy(poiSchemaVersion = PoiSchemaVersion.V4))
                    }
                }
                if (hasMapSource) OutputRow(
                    icon = Res.drawable.export_data,
                    title = strings["content.filtered_pbf"],
                    description = if (rawPbfOutputAvailable) {
                        strings["content.pbf_available"]
                    } else {
                        strings["content.pbf_unavailable"]
                    },
                    checked = exportSelection.filteredPbf && rawPbfOutputAvailable,
                    enabled = rawPbfOutputAvailable,
                ) { onExportSelectionChange(exportSelection.copy(filteredPbf = it)) }
                if (hasElevationSource) {
                    OutputRow(
                        icon = Res.drawable.export_data,
                        title = strings["content.elevation_data"],
                        description = strings["content.elevation_description"],
                        checked = exportSelection.elevationData,
                    ) { onExportSelectionChange(exportSelection.copy(elevationData = it)) }
                    if (exportSelection.elevationData) {
                        ElevationOutputFormat.entries.forEach { format ->
                            FormatVersionRow(
                                title = format.displayName,
                                description = strings[when (format) {
                                    ElevationOutputFormat.GEOTIFF -> "content.elevation_geotiff"
                                    ElevationOutputFormat.ESRI_ASCII_GRID -> "content.elevation_ascii"
                                    ElevationOutputFormat.SRTM_HGT -> "content.elevation_hgt"
                                    ElevationOutputFormat.DTED -> "content.elevation_dted"
                                }],
                                selected = exportSelection.elevationOutputFormat == format,
                            ) {
                                onExportSelectionChange(exportSelection.copy(elevationOutputFormat = format))
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun FormatVersionRow(
    title: String,
    description: String,
    selected: Boolean,
    onSelect: () -> Unit,
) {
    Row(
        modifier = Modifier.padding(start = 48.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        RadioButton(selected = selected, onClick = onSelect)
        Column {
            Text(title, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium)
            Text(
                description,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                style = MaterialTheme.typography.bodySmall,
            )
        }
    }
}

@Composable
private fun SelectionRow(title: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Checkbox(checked = checked, onCheckedChange = onCheckedChange)
        Spacer(Modifier.width(8.dp))
        Text(title)
    }
}

@Composable
private fun OutputRow(
    icon: DrawableResource,
    title: String,
    description: String,
    checked: Boolean,
    enabled: Boolean = true,
    onCheckedChange: (Boolean) -> Unit,
) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Checkbox(checked = checked, onCheckedChange = onCheckedChange, enabled = enabled)
        Image(painterResource(icon), contentDescription = null, modifier = Modifier.size(38.dp))
        Spacer(Modifier.width(10.dp))
        Column {
            Text(title, fontWeight = FontWeight.Medium)
            Text(description, color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodySmall)
        }
    }
}
