package de.trainingstagebuch.app.ui.screens

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import de.trainingstagebuch.app.R
import de.trainingstagebuch.app.ui.ErrorBanner
import de.trainingstagebuch.app.ui.ErrorSnackbarHost
import de.trainingstagebuch.app.ui.TrainingstagebuchTopBar
import de.trainingstagebuch.app.viewmodel.ClubSettingsStatus
import de.trainingstagebuch.app.viewmodel.ClubSettingsTab
import de.trainingstagebuch.app.viewmodel.ClubSettingsUiState
import de.trainingstagebuch.app.viewmodel.ClubSettingsViewModel

@Composable
fun ClubSettingsScreen(
    clubSettingsViewModel: ClubSettingsViewModel = viewModel()
) {
    val state by clubSettingsViewModel.state.collectAsState()
    val context = LocalContext.current
    val snackbarHostState = remember { SnackbarHostState() }
    var dismissedError by remember { mutableStateOf<de.trainingstagebuch.app.utils.UiText?>(null) }

    LaunchedEffect(state.errorMessage, state.successMessage) {
        state.errorMessage?.let {
            dismissedError = null
            snackbarHostState.showSnackbar(it.resolve(context))
        }
        state.successMessage?.let {
            snackbarHostState.showSnackbar(it.resolve(context))
        }
    }

    Scaffold(
        topBar = { TrainingstagebuchTopBar(title = stringResource(R.string.club_settings_title)) },
        snackbarHost = { ErrorSnackbarHost(hostState = snackbarHostState) }
    ) { paddingValues ->
        if (state.status == ClubSettingsStatus.Loading) {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(paddingValues),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                CircularProgressIndicator()
                Text(
                    text = stringResource(R.string.club_settings_loading),
                    modifier = Modifier.padding(top = 12.dp)
                )
            }
            return@Scaffold
        }

        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
                .padding(16.dp)
        ) {
            Text(
                text = stringResource(R.string.club_settings_title),
                style = MaterialTheme.typography.headlineSmall,
                modifier = Modifier.padding(bottom = 12.dp)
            )

            val currentError = state.errorMessage
            if (currentError != null && currentError != dismissedError) {
                ErrorBanner(
                    message = currentError.resolve(context),
                    onDismiss = { dismissedError = currentError },
                    modifier = Modifier.padding(bottom = 10.dp)
                )
            }

            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                Button(
                    onClick = { clubSettingsViewModel.onTabChanged(ClubSettingsTab.Settings) },
                    modifier = Modifier.weight(1f)
                ) {
                    Text(stringResource(R.string.club_settings_tab_settings))
                }
                Button(
                    onClick = { clubSettingsViewModel.onTabChanged(ClubSettingsTab.TrainingGroups) },
                    modifier = Modifier.weight(1f)
                ) {
                    Text(stringResource(R.string.club_settings_tab_groups))
                }
                Button(
                    onClick = { clubSettingsViewModel.onTabChanged(ClubSettingsTab.TrainingTimes) },
                    modifier = Modifier.weight(1f)
                ) {
                    Text(stringResource(R.string.club_settings_tab_times))
                }
            }

            when (state.activeTab) {
                ClubSettingsTab.Settings -> SettingsTab(state, clubSettingsViewModel)
                ClubSettingsTab.TrainingGroups -> TrainingGroupsTab(state, clubSettingsViewModel)
                ClubSettingsTab.TrainingTimes -> TrainingTimesTab(state, clubSettingsViewModel)
            }

            if (state.editingTrainingGroupId != null) {
                AlertDialog(
                    onDismissRequest = clubSettingsViewModel::cancelEditTrainingGroup,
                    title = { Text(stringResource(R.string.club_settings_dialog_edit_group_title)) },
                    text = {
                        OutlinedTextField(
                            value = state.editingTrainingGroupName,
                            onValueChange = clubSettingsViewModel::onEditingTrainingGroupNameChanged,
                            modifier = Modifier.fillMaxWidth(),
                            singleLine = true,
                            label = { Text(stringResource(R.string.club_settings_group_name_label)) }
                        )
                    },
                    confirmButton = {
                        Button(
                            onClick = clubSettingsViewModel::saveEditTrainingGroup,
                            enabled = !state.groupActionLoading
                        ) {
                            Text(stringResource(R.string.club_settings_update_button))
                        }
                    },
                    dismissButton = {
                        Button(
                            onClick = clubSettingsViewModel::cancelEditTrainingGroup,
                            enabled = !state.groupActionLoading
                        ) {
                            Text(stringResource(R.string.club_settings_cancel_button))
                        }
                    }
                )
            }

            if (state.editingTrainingTimeId != null) {
                val weekdayOptions = rememberWeekdayOptions()
                AlertDialog(
                    onDismissRequest = clubSettingsViewModel::cancelEditTrainingTime,
                    title = { Text(stringResource(R.string.club_settings_dialog_edit_time_title)) },
                    text = {
                        Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
                            WeekdayDropdown(
                                value = state.editingTrainingTimeWeekday,
                                onValueSelected = clubSettingsViewModel::onEditingTrainingTimeWeekdayChanged,
                                options = weekdayOptions
                            )
                            OutlinedTextField(
                                value = state.editingTrainingTimeStart,
                                onValueChange = clubSettingsViewModel::onEditingTrainingTimeStartChanged,
                                modifier = Modifier.fillMaxWidth(),
                                singleLine = true,
                                label = { Text(stringResource(R.string.club_settings_time_start_label)) }
                            )
                            OutlinedTextField(
                                value = state.editingTrainingTimeEnd,
                                onValueChange = clubSettingsViewModel::onEditingTrainingTimeEndChanged,
                                modifier = Modifier.fillMaxWidth(),
                                singleLine = true,
                                label = { Text(stringResource(R.string.club_settings_time_end_label)) }
                            )
                        }
                    },
                    confirmButton = {
                        Button(
                            onClick = clubSettingsViewModel::saveEditTrainingTime,
                            enabled = !state.timeActionLoading
                        ) {
                            Text(stringResource(R.string.club_settings_update_button))
                        }
                    },
                    dismissButton = {
                        Button(
                            onClick = clubSettingsViewModel::cancelEditTrainingTime,
                            enabled = !state.timeActionLoading
                        ) {
                            Text(stringResource(R.string.club_settings_cancel_button))
                        }
                    }
                )
            }
        }
    }
}

@Composable
private fun SettingsTab(state: ClubSettingsUiState, viewModel: ClubSettingsViewModel) {
    OutlinedTextField(
        value = state.greetingText,
        onValueChange = viewModel::onGreetingTextChanged,
        label = { Text(stringResource(R.string.club_settings_greeting_label)) },
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 12.dp),
        minLines = 5,
        maxLines = 12
    )

    OutlinedTextField(
        value = state.associationMemberNumber,
        onValueChange = viewModel::onAssociationMemberNumberChanged,
        label = { Text(stringResource(R.string.club_settings_association_member_number_label)) },
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 12.dp),
        singleLine = true
    )

    Button(
        onClick = viewModel::saveSettings,
        enabled = !state.saving,
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 16.dp)
    ) {
        if (state.saving) {
            CircularProgressIndicator(
                strokeWidth = 2.dp,
                modifier = Modifier.padding(vertical = 2.dp)
            )
        } else {
            Text(stringResource(R.string.club_settings_save_button))
        }
    }
}

@Composable
private fun TrainingGroupsTab(state: ClubSettingsUiState, viewModel: ClubSettingsViewModel) {
    OutlinedTextField(
        value = state.newTrainingGroupName,
        onValueChange = viewModel::onNewTrainingGroupNameChanged,
        label = { Text(stringResource(R.string.club_settings_group_name_label)) },
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 12.dp),
        singleLine = true
    )

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Button(
            onClick = viewModel::createTrainingGroup,
            enabled = !state.groupActionLoading,
            modifier = Modifier.weight(1f)
        ) {
            Text(stringResource(R.string.club_settings_group_create_button))
        }
        Button(
            onClick = viewModel::refreshTrainingGroups,
            enabled = !state.groupActionLoading,
            modifier = Modifier.weight(1f)
        ) {
            Text(stringResource(R.string.home_retry))
        }
    }

    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .padding(top = 10.dp)
    ) {
        items(state.trainingGroups, key = { it.id }) { group ->
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(vertical = 4.dp),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.SpaceBetween
            ) {
                Text(text = group.name, modifier = Modifier.weight(1f))
                Button(
                    onClick = { viewModel.startEditTrainingGroup(group.id, group.name) },
                    enabled = !state.groupActionLoading
                ) {
                    Text(stringResource(R.string.club_settings_edit_button))
                }
                Button(
                    onClick = { viewModel.deleteTrainingGroup(group.id) },
                    enabled = !state.groupActionLoading
                ) {
                    Text(stringResource(R.string.club_settings_delete_button))
                }
            }
        }
    }
}

@Composable
private fun TrainingTimesTab(state: ClubSettingsUiState, viewModel: ClubSettingsViewModel) {
    val weekdayOptions = rememberWeekdayOptions()

    GroupDropdown(
        value = state.newTrainingTimeGroupId,
        groups = state.trainingGroups,
        onValueSelected = viewModel::onNewTrainingTimeGroupIdChanged,
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 12.dp)
    )

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        WeekdayDropdown(
            value = state.newTrainingTimeWeekday,
            onValueSelected = viewModel::onNewTrainingTimeWeekdayChanged,
            options = weekdayOptions,
            modifier = Modifier.weight(1f)
        )
        OutlinedTextField(
            value = state.newTrainingTimeStart,
            onValueChange = viewModel::onNewTrainingTimeStartChanged,
            label = { Text(stringResource(R.string.club_settings_time_start_label)) },
            modifier = Modifier.weight(1f),
            singleLine = true
        )
        OutlinedTextField(
            value = state.newTrainingTimeEnd,
            onValueChange = viewModel::onNewTrainingTimeEndChanged,
            label = { Text(stringResource(R.string.club_settings_time_end_label)) },
            modifier = Modifier.weight(1f),
            singleLine = true
        )
    }

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Button(
            onClick = viewModel::createTrainingTime,
            enabled = !state.timeActionLoading,
            modifier = Modifier.weight(1f)
        ) {
            Text(stringResource(R.string.club_settings_time_create_button))
        }
        Button(
            onClick = viewModel::refreshTrainingTimes,
            enabled = !state.timeActionLoading,
            modifier = Modifier.weight(1f)
        ) {
            Text(stringResource(R.string.home_retry))
        }
    }

    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .padding(top = 10.dp)
    ) {
        state.trainingTimeGroups.forEach { group ->
            item(key = "group-${group.id}") {
                Text(
                    text = group.name,
                    style = MaterialTheme.typography.titleMedium,
                    modifier = Modifier.padding(vertical = 6.dp)
                )
            }
            items(group.trainingTimes, key = { it.id }) { time ->
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(vertical = 4.dp),
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.SpaceBetween
                ) {
                    Text(
                        text = stringResource(
                            R.string.club_settings_time_row,
                            time.weekday,
                            time.startTime.take(5),
                            time.endTime.take(5)
                        ),
                        modifier = Modifier.weight(1f)
                    )
                    Button(
                        onClick = {
                            viewModel.startEditTrainingTime(
                                timeId = time.id,
                                weekday = time.weekday,
                                start = time.startTime,
                                end = time.endTime
                            )
                        },
                        enabled = !state.timeActionLoading
                    ) {
                        Text(stringResource(R.string.club_settings_edit_button))
                    }
                    Button(
                        onClick = { viewModel.deleteTrainingTime(time.id) },
                        enabled = !state.timeActionLoading
                    ) {
                        Text(stringResource(R.string.club_settings_delete_button))
                    }
                }
            }
        }
    }
}

@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun GroupDropdown(
    value: String,
    groups: List<de.trainingstagebuch.app.repository.ClubTrainingGroup>,
    onValueSelected: (String) -> Unit,
    modifier: Modifier = Modifier
) {
    var expanded by remember { mutableStateOf(false) }
    val selectedLabel = groups.firstOrNull { it.id == value }?.name
        ?: if (value.isBlank()) stringResource(R.string.club_settings_time_group_id_label) else value

    ExposedDropdownMenuBox(
        expanded = expanded,
        onExpandedChange = { expanded = !expanded },
        modifier = modifier
    ) {
        OutlinedTextField(
            value = selectedLabel,
            onValueChange = {},
            readOnly = true,
            label = { Text(stringResource(R.string.club_settings_time_group_id_label)) },
            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
            modifier = Modifier
                .menuAnchor(type = MenuAnchorType.PrimaryNotEditable, enabled = true)
                .fillMaxWidth()
        )

        ExposedDropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false }
        ) {
            groups.forEach { group ->
                DropdownMenuItem(
                    text = { Text(group.name) },
                    onClick = {
                        onValueSelected(group.id)
                        expanded = false
                    }
                )
            }
        }
    }
}

@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun WeekdayDropdown(
    value: String,
    onValueSelected: (String) -> Unit,
    options: List<Pair<String, String>>,
    modifier: Modifier = Modifier
) {
    var expanded by remember { mutableStateOf(false) }
    val selectedLabel = options.firstOrNull { it.first == value }?.second
        ?: options.firstOrNull { it.first == "1" }?.second.orEmpty()

    ExposedDropdownMenuBox(
        expanded = expanded,
        onExpandedChange = { expanded = !expanded },
        modifier = modifier
    ) {
        OutlinedTextField(
            value = selectedLabel,
            onValueChange = {},
            readOnly = true,
            label = { Text(stringResource(R.string.club_settings_time_weekday_label)) },
            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
            modifier = Modifier
                .menuAnchor(type = MenuAnchorType.PrimaryNotEditable, enabled = true)
                .fillMaxWidth()
        )

        ExposedDropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false }
        ) {
            options.forEach { (raw, label) ->
                DropdownMenuItem(
                    text = { Text(label) },
                    onClick = {
                        onValueSelected(raw)
                        expanded = false
                    }
                )
            }
        }
    }
}

@Composable
private fun rememberWeekdayOptions(): List<Pair<String, String>> {
    return listOf(
        "0" to stringResource(R.string.club_settings_weekday_sunday),
        "1" to stringResource(R.string.club_settings_weekday_monday),
        "2" to stringResource(R.string.club_settings_weekday_tuesday),
        "3" to stringResource(R.string.club_settings_weekday_wednesday),
        "4" to stringResource(R.string.club_settings_weekday_thursday),
        "5" to stringResource(R.string.club_settings_weekday_friday),
        "6" to stringResource(R.string.club_settings_weekday_saturday)
    )
}
