package org.zaine.management.ui

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.zaine.management.data.api.CalendarEventDto
import org.zaine.management.data.api.TodayStatusDto
import org.zaine.management.data.api.WirdEntryDto
import java.time.LocalDate
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalAdjusters

@Composable
fun ZManagementRoot(rootViewModel: RootViewModel = hiltViewModel()) {
    var route by remember { mutableStateOf(rootViewModel.startRoute) }

    AppScaffold(route = route, onRoute = { route = it }) { padding ->
        when (val current = route) {
            AppRoute.Login -> LoginScreen(
                modifier = Modifier.padding(padding),
                onLoggedIn = { route = AppRoute.Today }
            )
            AppRoute.Today -> TodayScreen(
                modifier = Modifier.padding(padding),
                onMorning = { route = AppRoute.Morning },
                onEvening = { route = AppRoute.Evening },
                onCalendar = { route = AppRoute.Calendar },
                onEvent = { route = AppRoute.EventDetails(it) }
            )
            AppRoute.Morning -> MorningScreen(
                modifier = Modifier.padding(padding),
                onDone = { route = AppRoute.Today }
            )
            AppRoute.Evening -> EveningScreen(
                modifier = Modifier.padding(padding),
                onDone = { route = AppRoute.Today }
            )
            AppRoute.Calendar -> CalendarScreen(
                modifier = Modifier.padding(padding),
                onEvent = { route = AppRoute.EventDetails(it) }
            )
            AppRoute.Wird -> WirdScreen(modifier = Modifier.padding(padding))
            AppRoute.History -> HistoryScreen(modifier = Modifier.padding(padding))
            is AppRoute.EventDetails -> EventDetailsScreen(
                eventId = current.id,
                modifier = Modifier.padding(padding),
                onBack = { route = AppRoute.Calendar }
            )
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun AppScaffold(
    route: AppRoute,
    onRoute: (AppRoute) -> Unit,
    content: @Composable (PaddingValues) -> Unit
) {
    Scaffold(
        topBar = {
            CenterAlignedTopAppBar(title = {
                Text(
                    when (route) {
                        AppRoute.Login -> "Sign in"
                        AppRoute.Today -> "Today"
                        AppRoute.Morning -> "Morning"
                        AppRoute.Evening -> "Evening"
                        AppRoute.Calendar -> "Calendar"
                        AppRoute.Wird -> "Wird"
                        AppRoute.History -> "History"
                        is AppRoute.EventDetails -> "Event"
                    }
                )
            })
        },
        bottomBar = {
            if (route != AppRoute.Login) {
                NavigationBar {
                    NavigationBarItem(
                        selected = route == AppRoute.Today,
                        onClick = { onRoute(AppRoute.Today) },
                        icon = {},
                        label = { Text("Today") }
                    )
                    NavigationBarItem(
                        selected = route == AppRoute.Calendar,
                        onClick = { onRoute(AppRoute.Calendar) },
                        icon = {},
                        label = { Text("Calendar") }
                    )
                    NavigationBarItem(
                        selected = route == AppRoute.Wird,
                        onClick = { onRoute(AppRoute.Wird) },
                        icon = {},
                        label = { Text("Wird") }
                    )
                    NavigationBarItem(
                        selected = route == AppRoute.History,
                        onClick = { onRoute(AppRoute.History) },
                        icon = {},
                        label = { Text("History") }
                    )
                }
            }
        },
        content = content
    )
}

@Composable
private fun LoginScreen(
    modifier: Modifier = Modifier,
    onLoggedIn: () -> Unit,
    viewModel: LoginViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    LaunchedEffect(state.loggedIn) {
        if (state.loggedIn) onLoggedIn()
    }

    Column(
        modifier = modifier.fillMaxSize().padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        OutlinedTextField(
            value = state.baseUrl,
            onValueChange = viewModel::setBaseUrl,
            label = { Text("Backend URL") },
            modifier = Modifier.fillMaxWidth(),
            singleLine = true
        )
        OutlinedTextField(
            value = state.username,
            onValueChange = viewModel::setUsername,
            label = { Text("Username") },
            modifier = Modifier.fillMaxWidth(),
            singleLine = true
        )
        OutlinedTextField(
            value = state.password,
            onValueChange = viewModel::setPassword,
            label = { Text("Password") },
            modifier = Modifier.fillMaxWidth(),
            singleLine = true,
            visualTransformation = PasswordVisualTransformation()
        )
        if (state.error != null) Text(state.error!!, color = MaterialTheme.colorScheme.error)
        Button(onClick = viewModel::login, enabled = !state.loading, modifier = Modifier.fillMaxWidth()) {
            Text(if (state.loading) "Signing in" else "Sign in")
        }
    }
}

@Composable
private fun TodayScreen(
    modifier: Modifier = Modifier,
    onMorning: () -> Unit,
    onEvening: () -> Unit,
    onCalendar: () -> Unit,
    onEvent: (Long) -> Unit,
    viewModel: TodayViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    ScreenState(state.loading, state.error, viewModel::refresh) {
        val data = state.data
        LazyColumn(
            modifier = modifier.fillMaxSize(),
            contentPadding = PaddingValues(16.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            item {
                SectionCard("Check-ins") {
                    val status = data?.status
                    Text("Morning: ${if (status?.morningDone == true) "done" else "not done"}")
                    Text("Evening: ${if (status?.eveningDone == true) "done" else "pending"}")
                    Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                        Button(onClick = onMorning, modifier = Modifier.weight(1f)) { Text("Morning") }
                        Button(onClick = onEvening, modifier = Modifier.weight(1f)) { Text("Evening") }
                    }
                }
            }
            item {
                SectionCard("Today") {
                    val status = data?.status
                    Text("Fajr: ${yesNo(status?.fajr)}")
                    Text("Quran: ${yesNo(status?.quran)}")
                    Text("Exercise: ${yesNo(status?.exercise)}")
                    Text("Duties: ${yesNo(status?.duties)}")
                    Text("Zikr: ${yesNo(status?.zikr)}")
                    Text("Salah: ${yesNo(status?.salah)}")
                }
            }
            item {
                SectionCard("Today's events") {
                    if (data?.events.isNullOrEmpty()) {
                        Text("No events today")
                    } else {
                        data.events.forEach { event ->
                            EventRow(event = event, onClick = { onEvent(event.id) })
                        }
                    }
                    TextButton(onClick = onCalendar) { Text("Open calendar") }
                }
            }
        }
    }
}

@Composable
private fun MorningScreen(
    modifier: Modifier = Modifier,
    onDone: () -> Unit,
    viewModel: MorningViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    LaunchedEffect(state.saved) { if (state.saved) onDone() }
    LazyColumn(
        modifier = modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        item {
            OutlinedTextField(
                value = state.sleepHours,
                onValueChange = viewModel::setSleepHours,
                label = { Text("Sleep hours") },
                modifier = Modifier.fillMaxWidth(),
                singleLine = true
            )
        }
        item { CheckRow("Fajr", state.fajr, viewModel::setFajr) }
        item { CheckRow("Quran", state.quran, viewModel::setQuran) }
        item { CheckRow("Exercise", state.exercise, viewModel::setExercise) }
        item { MultiLineField("Note", state.note, viewModel::setNote) }
        item {
            if (state.error != null) Text(state.error!!, color = MaterialTheme.colorScheme.error)
            Button(onClick = viewModel::submit, enabled = !state.loading, modifier = Modifier.fillMaxWidth()) {
                Text(if (state.loading) "Saving" else "Save morning")
            }
        }
    }
}

@Composable
private fun EveningScreen(
    modifier: Modifier = Modifier,
    onDone: () -> Unit,
    viewModel: EveningViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    LaunchedEffect(state.saved) { if (state.saved) onDone() }
    LazyColumn(
        modifier = modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        item { CheckRow("Duties", state.duties, viewModel::setDuties) }
        item { CheckRow("Zikr", state.zikr, viewModel::setZikr) }
        item { CheckRow("Salah", state.salah, viewModel::setSalah) }
        item { MultiLineField("Reflection", state.reflection, viewModel::setReflection) }
        item {
            if (state.error != null) Text(state.error!!, color = MaterialTheme.colorScheme.error)
            Button(onClick = viewModel::submit, enabled = !state.loading, modifier = Modifier.fillMaxWidth()) {
                Text(if (state.loading) "Saving" else "Save evening")
            }
        }
    }
}

@Composable
private fun CalendarScreen(
    modifier: Modifier = Modifier,
    onEvent: (Long) -> Unit,
    viewModel: CalendarViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    LazyColumn(
        modifier = modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        item {
            Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                CalendarModeButton("Day", state.mode == CalendarViewMode.Day) { viewModel.setMode(CalendarViewMode.Day) }
                CalendarModeButton("Week", state.mode == CalendarViewMode.Week) { viewModel.setMode(CalendarViewMode.Week) }
                CalendarModeButton("Month", state.mode == CalendarViewMode.Month) { viewModel.setMode(CalendarViewMode.Month) }
            }
        }
        item {
            Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
                TextButton(onClick = {
                    when (state.mode) {
                        CalendarViewMode.Day -> viewModel.previousDay()
                        CalendarViewMode.Week -> viewModel.previousWeek()
                        CalendarViewMode.Month -> viewModel.previousMonth()
                    }
                }) { Text("Previous") }
                Text(
                    calendarTitle(state),
                    style = MaterialTheme.typography.titleMedium
                )
                TextButton(onClick = {
                    when (state.mode) {
                        CalendarViewMode.Day -> viewModel.nextDay()
                        CalendarViewMode.Week -> viewModel.nextWeek()
                        CalendarViewMode.Month -> viewModel.nextMonth()
                    }
                }) { Text("Next") }
            }
        }
        item {
            ScreenState(state.loading, state.error, viewModel::refresh) {
                Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
                    if (state.events.isEmpty()) Text("No events")
                    state.events.forEach { event -> EventRow(event, onClick = { onEvent(event.id) }) }
                }
            }
        }
    }
}

@Composable
private fun WirdScreen(
    modifier: Modifier = Modifier,
    viewModel: WirdViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    LazyColumn(
        modifier = modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        item {
            SectionCard("Add wird entry") {
                OutlinedTextField(
                    value = state.date,
                    onValueChange = viewModel::setDate,
                    label = { Text("Date") },
                    modifier = Modifier.fillMaxWidth(),
                    singleLine = true
                )
                OutlinedTextField(
                    value = state.wirdType,
                    onValueChange = viewModel::setWirdType,
                    label = { Text("Type") },
                    modifier = Modifier.fillMaxWidth(),
                    singleLine = true
                )
                Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) {
                    listOf("durood", "quran", "istighfar").forEach { type ->
                        TextButton(onClick = { viewModel.setWirdType(type) }) { Text(type) }
                    }
                }
                OutlinedTextField(
                    value = state.value,
                    onValueChange = viewModel::setValue,
                    label = { Text("Value") },
                    modifier = Modifier.fillMaxWidth(),
                    singleLine = true
                )
                MultiLineField("Notes", state.notes, viewModel::setNotes)
                if (state.saved) Text("Saved")
                if (state.error != null) Text(state.error!!, color = MaterialTheme.colorScheme.error)
                Button(onClick = viewModel::submit, enabled = !state.loading, modifier = Modifier.fillMaxWidth()) {
                    Text(if (state.loading) "Saving" else "Save wird")
                }
            }
        }
        item {
            SectionCard("Today's entries") {
                ScreenState(state.loading, state.error, viewModel::refresh) {
                    if (state.entries.isEmpty()) Text("No entries today")
                    state.entries.forEach { WirdRow(it) }
                }
            }
        }
    }
}

@Composable
private fun HistoryScreen(
    modifier: Modifier = Modifier,
    viewModel: HistoryViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    LazyColumn(
        modifier = modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        item {
            Text(
                "${state.from.format(DateTimeFormatter.ofPattern("d MMM"))} - ${state.to.format(DateTimeFormatter.ofPattern("d MMM yyyy"))}",
                style = MaterialTheme.typography.titleMedium
            )
        }
        item {
            ScreenState(state.loading, state.error, viewModel::refresh) {
                Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
                    SectionCard("Check-ins") {
                        if (state.checkins.isEmpty()) Text("No check-ins")
                        state.checkins.forEach { CheckinHistoryRow(it) }
                    }
                    SectionCard("Wird") {
                        if (state.wirdEntries.isEmpty()) Text("No wird entries")
                        state.wirdEntries.forEach { WirdRow(it) }
                    }
                }
            }
        }
    }
}

@Composable
private fun EventDetailsScreen(
    eventId: Long,
    modifier: Modifier = Modifier,
    onBack: () -> Unit,
    viewModel: EventDetailsViewModel = hiltViewModel()
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    LaunchedEffect(eventId) { viewModel.load(eventId) }
    ScreenState(state.loading, state.error, { viewModel.load(eventId) }) {
        val event = state.event
        Column(
            modifier = modifier.fillMaxSize().padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            TextButton(onClick = onBack) { Text("Back") }
            if (event != null) {
                Text(event.title, style = MaterialTheme.typography.headlineSmall, fontWeight = FontWeight.SemiBold)
                Text("${formatEventTime(event.startsAt)} - ${formatEventTime(event.endsAt)}")
                if (!event.location.isNullOrBlank()) Text(event.location)
                if (!event.description.isNullOrBlank()) Text(event.description)
                Text("Source: ${event.source}", style = MaterialTheme.typography.bodySmall)
            }
        }
    }
}

@Composable
private fun EventRow(event: CalendarEventDto, onClick: () -> Unit) {
    Column(
        modifier = Modifier.fillMaxWidth().clickable(onClick = onClick).padding(vertical = 8.dp)
    ) {
        Text(event.title, style = MaterialTheme.typography.bodyLarge, fontWeight = FontWeight.Medium)
        Spacer(Modifier.height(2.dp))
        Row {
            Text(formatEventTime(event.startsAt), style = MaterialTheme.typography.bodySmall)
            if (!event.location.isNullOrBlank()) {
                Spacer(Modifier.width(8.dp))
                Text(event.location, style = MaterialTheme.typography.bodySmall)
            }
        }
        HorizontalDivider(Modifier.padding(top = 8.dp))
    }
}

@Composable
private fun WirdRow(entry: WirdEntryDto) {
    Column(modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)) {
        Text("${entry.date}  ${entry.wirdType}: ${entry.value}", fontWeight = FontWeight.Medium)
        if (!entry.notes.isNullOrBlank()) Text(entry.notes, style = MaterialTheme.typography.bodySmall)
        HorizontalDivider(Modifier.padding(top = 6.dp))
    }
}

@Composable
private fun CheckinHistoryRow(status: TodayStatusDto) {
    Column(modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)) {
        Text(status.date, fontWeight = FontWeight.Medium)
        Text("Morning: Fajr ${yesNo(status.fajr)}, Quran ${yesNo(status.quran)}, Exercise ${yesNo(status.exercise)}, Sleep ${status.sleepHours ?: "-"}")
        Text("Evening: Duties ${yesNo(status.duties)}, Zikr ${yesNo(status.zikr)}, Salah ${yesNo(status.salah)}")
        if (!status.reflection.isNullOrBlank()) Text(status.reflection, style = MaterialTheme.typography.bodySmall)
        HorizontalDivider(Modifier.padding(top = 6.dp))
    }
}

@Composable
private fun CheckRow(label: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit) {
    Row(
        modifier = Modifier.fillMaxWidth().clickable { onCheckedChange(!checked) }.padding(vertical = 6.dp),
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Text(label, style = MaterialTheme.typography.bodyLarge)
        Checkbox(checked = checked, onCheckedChange = onCheckedChange)
    }
}

@Composable
private fun RowScope.CalendarModeButton(label: String, selected: Boolean, onClick: () -> Unit) {
    if (selected) {
        Button(onClick = onClick, modifier = Modifier.weight(1f)) { Text(label) }
    } else {
        TextButton(onClick = onClick, modifier = Modifier.weight(1f)) { Text(label) }
    }
}

private fun calendarTitle(state: CalendarUiState): String =
    when (state.mode) {
        CalendarViewMode.Day -> state.selectedDate.format(DateTimeFormatter.ofPattern("EEE d MMM yyyy"))
        CalendarViewMode.Week -> {
            val start = state.selectedDate.with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY))
            val end = start.plusDays(6)
            "${start.format(DateTimeFormatter.ofPattern("d MMM"))} - ${end.format(DateTimeFormatter.ofPattern("d MMM yyyy"))}"
        }
        CalendarViewMode.Month -> "${state.selectedMonth.month.name.lowercase().replaceFirstChar { it.uppercase() }} ${state.selectedMonth.year}"
    }

private fun yesNo(value: Boolean?): String = if (value == true) "yes" else "no"

private fun formatEventTime(value: String): String =
    runCatching {
        OffsetDateTime.parse(value).format(DateTimeFormatter.ofPattern("EEE d MMM, HH:mm"))
    }.getOrDefault(value)
