package de.tsschulz.timeclock.ui.admin

import android.app.DatePickerDialog
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
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.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import de.tsschulz.timeclock.data.api.HolidayDto
import de.tsschulz.timeclock.data.api.RoleUserDto
import de.tsschulz.timeclock.ui.components.TcButton
import de.tsschulz.timeclock.ui.components.TcCard
import de.tsschulz.timeclock.ui.components.TcError
import de.tsschulz.timeclock.ui.components.TcLoading
import de.tsschulz.timeclock.ui.components.TcTextField
import de.tsschulz.timeclock.ui.model.ButtonVariant
import de.tsschulz.timeclock.ui.theme.TcColors
import de.tsschulz.timeclock.ui.theme.TcRadius
import de.tsschulz.timeclock.ui.theme.TcSpacing
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Locale

@Composable
fun HolidaysAdminScreen(
    state: AdminUiState,
    isTablet: Boolean,
    onCreate: (String, Double, String, List<String>) -> Unit,
    onDelete: (String) -> Unit,
) {
    var date by rememberSaveable { mutableStateOf(LocalDate.now().toGermanDate()) }
    var hours by rememberSaveable { mutableStateOf("8") }
    var description by rememberSaveable { mutableStateOf("") }
    var stateIds by rememberSaveable { mutableStateOf("") }

    AdminFrame(state) {
        if (isTablet) {
            Row(horizontalArrangement = Arrangement.spacedBy(TcSpacing.Xl), modifier = Modifier.fillMaxWidth()) {
                HolidayForm(
                    state = state,
                    date = date,
                    onDate = { date = it },
                    hours = hours,
                    onHours = { hours = it },
                    description = description,
                    onDescription = { description = it },
                    stateIds = stateIds,
                    onStateIds = { stateIds = it },
                    onCreate = {
                        normalizeHolidayDate(date)?.let { isoDate ->
                            onCreate(isoDate, hours.toDoubleOrNull() ?: 8.0, description, parseStateIds(stateIds))
                            date = LocalDate.parse(isoDate).toGermanDate()
                            description = ""
                        }
                    },
                    modifier = Modifier.weight(0.9f),
                )
                Column(modifier = Modifier.weight(1.1f), verticalArrangement = Arrangement.spacedBy(TcSpacing.Lg)) {
                    HolidayList("Zukünftige Feiertage", state.futureHolidays, onDelete)
                    HolidayList("Vergangene Feiertage", state.pastHolidays, onDelete)
                }
            }
        } else {
            HolidayForm(
                state = state,
                date = date,
                onDate = { date = it },
                hours = hours,
                onHours = { hours = it },
                description = description,
                onDescription = { description = it },
                stateIds = stateIds,
                onStateIds = { stateIds = it },
                onCreate = {
                    normalizeHolidayDate(date)?.let { isoDate ->
                        onCreate(isoDate, hours.toDoubleOrNull() ?: 8.0, description, parseStateIds(stateIds))
                        date = LocalDate.parse(isoDate).toGermanDate()
                        description = ""
                    }
                },
            )
            HolidayList("Zukünftige Feiertage", state.futureHolidays, onDelete)
            HolidayList("Vergangene Feiertage", state.pastHolidays, onDelete)
        }
    }
}

@Composable
fun RolesAdminScreen(
    state: AdminUiState,
    onUpdateRole: (String, Int) -> Unit,
) {
    AdminFrame(state) {
        TcCard {
            SectionTitle("Rechte")
            Text(
                text = "Als Administrator können Sie hier die Berechtigungen anderer Benutzer verwalten.",
                color = TcColors.TextMuted,
                fontSize = 14.sp,
            )
        }
        ListCard("Benutzer", state.users) { user ->
            UserRoleRow(user, onUpdateRole)
        }
    }
}

@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun HolidayForm(
    state: AdminUiState,
    date: String,
    onDate: (String) -> Unit,
    hours: String,
    onHours: (String) -> Unit,
    description: String,
    onDescription: (String) -> Unit,
    stateIds: String,
    onStateIds: (String) -> Unit,
    onCreate: () -> Unit,
    modifier: Modifier = Modifier,
) {
    FormCard("Feiertag hinzufügen", modifier) {
        HolidayDateInput(date, onDate)
        TcTextField("Freie Stunden", hours, onHours, placeholder = "8")
        TcTextField("Beschreibung", description, onDescription, placeholder = "z.B. Tag der Deutschen Einheit")
        if (state.holidayStates.isNotEmpty()) {
            Text("Bundesländer", color = TcColors.TextMuted, fontSize = 13.sp)
            FlowRow(
                horizontalArrangement = Arrangement.spacedBy(TcSpacing.Sm),
                verticalArrangement = Arrangement.spacedBy(TcSpacing.Sm),
            ) {
                val selected = parseStateIds(stateIds).toSet()
                state.holidayStates.forEach { item ->
                    TcButton(
                        text = item.name,
                        variant = if (item.id in selected) ButtonVariant.Primary else ButtonVariant.Default,
                        onClick = { onStateIds(toggleStateId(stateIds, item.id)) },
                    )
                }
            }
        }
        TcButton("Feiertag hinzufügen", variant = ButtonVariant.Primary, onClick = {
            if (date.isNotBlank() && description.isNotBlank()) onCreate()
        })
    }
}

@Composable
private fun HolidayDateInput(value: String, onValueChange: (String) -> Unit) {
    val context = LocalContext.current
    val selectedDate = parseHolidayDate(value) ?: LocalDate.now()
    Row(horizontalArrangement = Arrangement.spacedBy(TcSpacing.Sm), verticalAlignment = Alignment.Bottom) {
        TcTextField(
            label = "Datum",
            value = value,
            onValueChange = onValueChange,
            modifier = Modifier.weight(1f),
            placeholder = "TT.MM.JJJJ oder YYYY-MM-DD",
        )
        TcButton(
            text = "Auswählen",
            variant = ButtonVariant.Default,
            onClick = {
                DatePickerDialog(
                    context,
                    { _, year, month, day ->
                        onValueChange(LocalDate.of(year, month + 1, day).toGermanDate())
                    },
                    selectedDate.year,
                    selectedDate.monthValue - 1,
                    selectedDate.dayOfMonth,
                ).show()
            },
        )
    }
}

@Composable
private fun HolidayList(title: String, holidays: List<HolidayDto>, onDelete: (String) -> Unit) {
    ListCard(title, holidays) { holiday -> HolidayRow(holiday, onDelete) }
}

@Composable
private fun HolidayRow(holiday: HolidayDto, onDelete: (String) -> Unit) = DataRow(
    title = holiday.description,
    details = "${holiday.date.toDisplayDate()} - ${holiday.hours} h - ${
        if (holiday.isFederal || holiday.states.isEmpty()) "Bundesfeiertag" else holiday.states.joinToString()
    }",
    action = "Löschen",
    variant = ButtonVariant.Danger,
    onAction = { onDelete(holiday.id) },
)

@Composable
private fun UserRoleRow(user: RoleUserDto, onUpdateRole: (String, Int) -> Unit) {
    val isAdmin = user.role == 1 || user.roleString == "admin"
    DataRow(
        title = user.fullName,
        details = "${user.stateName ?: "-"} - ${if (isAdmin) "Administrator" else "Benutzer"}",
        action = if (isAdmin) "Zu Benutzer" else "Zu Admin",
        variant = if (isAdmin) ButtonVariant.Secondary else ButtonVariant.Primary,
        onAction = { onUpdateRole(user.id, if (isAdmin) 0 else 1) },
    )
}

@Composable
private fun AdminFrame(state: AdminUiState, content: @Composable ColumnScope.() -> Unit) {
    Column(verticalArrangement = Arrangement.spacedBy(TcSpacing.Lg)) {
        if (state.loading) TcLoading("Lade Daten...")
        state.error?.let { TcError(it) }
        state.success?.let {
            TcCard { Text(it, color = TcColors.Success, fontSize = 14.sp, fontWeight = FontWeight.Medium) }
        }
        content()
    }
}

@Composable
private fun FormCard(title: String, modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) {
    TcCard(modifier = modifier) {
        SectionTitle(title)
        Column(verticalArrangement = Arrangement.spacedBy(TcSpacing.Md), content = content)
    }
}

@Composable
private fun <T> ListCard(title: String, items: List<T>, row: @Composable (T) -> Unit) {
    TcCard {
        SectionTitle(title)
        if (items.isEmpty()) {
            Text("Keine Einträge vorhanden.", color = TcColors.TextMuted, fontSize = 14.sp)
        } else {
            Column(verticalArrangement = Arrangement.spacedBy(TcSpacing.Sm)) {
                items.forEach { item -> row(item) }
            }
        }
    }
}

@Composable
private fun DataRow(
    title: String,
    details: String,
    action: String,
    variant: ButtonVariant,
    onAction: () -> Unit,
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .background(TcColors.Background, RoundedCornerShape(TcRadius.Medium))
            .border(1.dp, TcColors.Border, RoundedCornerShape(TcRadius.Medium))
            .padding(TcSpacing.Md),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(TcSpacing.Md),
    ) {
        Column(modifier = Modifier.weight(1f)) {
            Text(title, color = TcColors.Text, fontSize = 14.sp, fontWeight = FontWeight.SemiBold)
            Text(details, color = TcColors.TextMuted, fontSize = 13.sp)
        }
        TcButton(action, variant = variant, onClick = onAction)
    }
}

@Composable
private fun SectionTitle(title: String) {
    Text(
        text = title,
        color = TcColors.Text,
        fontSize = 18.sp,
        fontWeight = FontWeight.SemiBold,
        modifier = Modifier.padding(bottom = TcSpacing.Sm),
    )
}

private fun parseStateIds(raw: String): List<String> =
    raw.split(',', ';', ' ')
        .map { it.trim() }
        .filter { it.isNotBlank() }

private fun toggleStateId(raw: String, id: String): String {
    val ids = parseStateIds(raw).toMutableList()
    if (id in ids) ids.remove(id) else ids.add(id)
    return ids.joinToString(",")
}

private val germanDateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.GERMANY)

private fun LocalDate.toGermanDate(): String = format(germanDateFormatter)

private fun parseHolidayDate(raw: String): LocalDate? {
    val value = raw.trim()
    if (value.isBlank()) return null
    return runCatching { LocalDate.parse(value) }
        .recoverCatching { LocalDate.parse(value, germanDateFormatter) }
        .getOrNull()
}

private fun normalizeHolidayDate(raw: String): String? = parseHolidayDate(raw)?.toString()

private fun String?.toDisplayDate(): String {
    if (this.isNullOrBlank()) return "-"
    return runCatching {
        val p = LocalDate.parse(this)
        "%02d.%02d.%04d".format(p.dayOfMonth, p.monthValue, p.year)
    }.getOrDefault(this)
}
