package com.atridad.ascently.ui.screens

import android.content.Context
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.List
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Warning
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.content.edit
import com.atridad.ascently.R
import com.atridad.ascently.data.model.ClimbSession
import com.atridad.ascently.data.model.SessionStatus
import com.atridad.ascently.ui.components.ActiveSessionBanner
import com.atridad.ascently.ui.components.SyncIndicator
import com.atridad.ascently.ui.viewmodel.ClimbViewModel
import com.atridad.ascently.utils.DateFormatUtils
import java.time.LocalDate
import java.time.YearMonth
import java.time.format.DateTimeFormatter
import java.time.format.TextStyle
import java.util.Locale

enum class ViewMode {
    LIST,
    CALENDAR,
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SessionsScreen(viewModel: ClimbViewModel, onNavigateToSessionDetail: (String) -> Unit) {
    val context = LocalContext.current
    val sessions by viewModel.sessions.collectAsState()
    val gyms by viewModel.gyms.collectAsState()
    val activeSession by viewModel.activeSession.collectAsState()
    val uiState by viewModel.uiState.collectAsState()

    val sharedPreferences =
        context.getSharedPreferences("SessionsPreferences", Context.MODE_PRIVATE)
    val savedViewMode = sharedPreferences.getString("view_mode", "LIST")
    var viewMode by remember {
        mutableStateOf(if (savedViewMode == "CALENDAR") ViewMode.CALENDAR else ViewMode.LIST)
    }
    var selectedMonth by remember { mutableStateOf(YearMonth.now()) }
    var selectedDate by remember { mutableStateOf<LocalDate?>(LocalDate.now()) }

    val completedSessions = remember(sessions) {
        sessions.filter { it.status == SessionStatus.COMPLETED }
    }
    val activeSessionGym = remember(activeSession, gyms) {
        activeSession?.let { session -> gyms.find { it.id == session.gymId } }
    }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(12.dp),
        ) {
            Icon(
                painter = painterResource(id = R.drawable.ic_mountains),
                contentDescription = "Ascently Logo",
                modifier = Modifier.size(32.dp),
                tint = MaterialTheme.colorScheme.primary,
            )
            Text(
                text = "Climbing Sessions",
                style = MaterialTheme.typography.headlineMedium,
                fontWeight = FontWeight.Bold,
                modifier = Modifier.weight(1f),
            )

            IconButton(
                onClick = {
                    viewMode =
                        if (viewMode == ViewMode.LIST) ViewMode.CALENDAR else ViewMode.LIST
                    selectedDate = null
                    sharedPreferences.edit { putString("view_mode", viewMode.name) }
                },
            ) {
                Icon(
                    imageVector =
                    if (viewMode == ViewMode.LIST) {
                        Icons.Default.CalendarMonth
                    } else {
                        Icons.AutoMirrored.Filled.List
                    },
                    contentDescription =
                    if (viewMode == ViewMode.LIST) "Calendar View" else "List View",
                    tint = MaterialTheme.colorScheme.primary,
                )
            }

            SyncIndicator(isSyncing = viewModel.syncService.isSyncing)
        }

        Spacer(modifier = Modifier.height(16.dp))

        ActiveSessionBanner(
            activeSession = activeSession,
            gym = activeSessionGym,
            onSessionClick = { activeSession?.let { onNavigateToSessionDetail(it.id) } },
            onEndSession = { activeSession?.let { viewModel.endSession(context, it.id) } },
        )

        if (activeSession != null) {
            Spacer(modifier = Modifier.height(16.dp))
        }

        if (completedSessions.isEmpty() && activeSession == null) {
            EmptyStateMessage(
                title = if (gyms.isEmpty()) "No Gyms Available" else "No Sessions Yet",
                message =
                if (gyms.isEmpty()) {
                    "Add a gym first to start tracking your climbing sessions!"
                } else {
                    "Start your first climbing session!"
                },
                onActionClick = {},
                actionText = "",
            )
        } else {
            when (viewMode) {
                ViewMode.LIST -> {
                    LazyColumn {
                        items(completedSessions, key = { it.id }) { session ->
                            SessionCard(
                                session = session,
                                gymName = gyms.find { it.id == session.gymId }?.name
                                    ?: "Unknown Gym",
                                onClick = { onNavigateToSessionDetail(session.id) },
                            )
                            Spacer(modifier = Modifier.height(8.dp))
                        }
                    }
                }
                ViewMode.CALENDAR -> {
                    CalendarView(
                        sessions = completedSessions,
                        gyms = gyms,
                        selectedMonth = selectedMonth,
                        onMonthChange = { selectedMonth = it },
                        selectedDate = selectedDate,
                        onDateSelected = { selectedDate = it },
                        onNavigateToSessionDetail = onNavigateToSessionDetail,
                    )
                }
            }
        }
    }

    uiState.message?.let { message ->
        LaunchedEffect(message) {
            kotlinx.coroutines.delay(5000)
            viewModel.clearMessage()
        }

        Card(
            modifier = Modifier.fillMaxWidth().padding(16.dp),
            colors =
            CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.primaryContainer,
            ),
            shape = RoundedCornerShape(12.dp),
        ) {
            Row(
                modifier = Modifier.fillMaxWidth().padding(16.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Icon(
                    Icons.Default.CheckCircle,
                    contentDescription = null,
                    tint = MaterialTheme.colorScheme.primary,
                )
                Spacer(modifier = Modifier.width(8.dp))
                Text(
                    text = message,
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onPrimaryContainer,
                )
            }
        }
    }

    uiState.error?.let { error ->
        LaunchedEffect(error) {
            kotlinx.coroutines.delay(5000)
            viewModel.clearError()
        }

        Card(
            modifier = Modifier.fillMaxWidth().padding(16.dp),
            colors =
            CardDefaults.cardColors(
                containerColor = MaterialTheme.colorScheme.errorContainer,
            ),
            shape = RoundedCornerShape(12.dp),
        ) {
            Row(
                modifier = Modifier.fillMaxWidth().padding(16.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Icon(
                    Icons.Default.Warning,
                    contentDescription = null,
                    tint = MaterialTheme.colorScheme.error,
                )
                Spacer(modifier = Modifier.width(8.dp))
                Text(
                    text = error,
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onErrorContainer,
                )
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SessionCard(session: ClimbSession, gymName: String, onClick: () -> Unit) {
    val formattedDate = remember(session.date) {
        DateFormatUtils.formatDateForDisplay(session.date)
    }

    Card(onClick = onClick, modifier = Modifier.fillMaxWidth()) {
        Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
            ) {
                Text(
                    text = gymName,
                    style = MaterialTheme.typography.titleMedium,
                    fontWeight = FontWeight.Bold,
                )
                Text(
                    text = formattedDate,
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
            }

            Spacer(modifier = Modifier.height(4.dp))

            session.duration?.let { duration ->
                Text(
                    text = "Duration: $duration minutes",
                    style = MaterialTheme.typography.bodyMedium,
                )
            }

            session.notes?.let { notes ->
                if (notes.isNotBlank()) {
                    Spacer(modifier = Modifier.height(4.dp))
                    Text(
                        text = notes,
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                        maxLines = 2,
                    )
                }
            }
        }
    }
}

@Composable
fun EmptyStateMessage(
    title: String,
    message: String,
    onActionClick: () -> Unit,
    actionText: String,
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    ) {
        Text(
            text = title,
            style = MaterialTheme.typography.headlineSmall,
            fontWeight = FontWeight.Bold,
            textAlign = TextAlign.Center,
        )

        Spacer(modifier = Modifier.height(8.dp))

        Text(
            text = message,
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            textAlign = TextAlign.Center,
        )

        if (actionText.isNotEmpty()) {
            Spacer(modifier = Modifier.height(16.dp))

            Button(onClick = onActionClick) { Text(actionText) }
        }
    }
}

@Composable
fun CalendarView(
    sessions: List<ClimbSession>,
    gyms: List<com.atridad.ascently.data.model.Gym>,
    selectedMonth: YearMonth,
    onMonthChange: (YearMonth) -> Unit,
    selectedDate: LocalDate?,
    onDateSelected: (LocalDate?) -> Unit,
    onNavigateToSessionDetail: (String) -> Unit,
) {
    val sessionsByDate =
        remember(sessions) {
            sessions.groupBy {
                try {
                    java.time.Instant.parse(it.date)
                        .atZone(java.time.ZoneId.systemDefault())
                        .toLocalDate()
                } catch (_: Exception) {
                    LocalDate.parse(it.date, DateTimeFormatter.ISO_LOCAL_DATE)
                }
            }
        }

    val firstDayOfMonth = selectedMonth.atDay(1)
    val daysInMonth = selectedMonth.lengthOfMonth()
    val firstDayOfWeek = firstDayOfMonth.dayOfWeek.value % 7
    val totalCells =
        ((firstDayOfWeek + daysInMonth) / 7.0).let {
            if (it == it.toInt().toDouble()) it.toInt() * 7 else (it.toInt() + 1) * 7
        }
    val numRows = totalCells / 7

    LazyColumn(modifier = Modifier.fillMaxSize()) {
        item {
            Card(
                modifier = Modifier.fillMaxWidth(),
                colors =
                CardDefaults.cardColors(
                    containerColor = MaterialTheme.colorScheme.surfaceVariant,
                ),
            ) {
                Column(
                    modifier =
                    Modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 12.dp),
                    horizontalAlignment = Alignment.CenterHorizontally,
                ) {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween,
                        verticalAlignment = Alignment.CenterVertically,
                    ) {
                        IconButton(onClick = { onMonthChange(selectedMonth.minusMonths(1)) }) {
                            Text("‹", style = MaterialTheme.typography.headlineMedium)
                        }

                        Text(
                            text =
                            "${selectedMonth.month.getDisplayName(TextStyle.FULL, Locale.getDefault())} ${selectedMonth.year}",
                            style = MaterialTheme.typography.titleMedium,
                            fontWeight = FontWeight.Bold,
                        )

                        IconButton(onClick = { onMonthChange(selectedMonth.plusMonths(1)) }) {
                            Text("›", style = MaterialTheme.typography.headlineMedium)
                        }
                    }

                    Spacer(modifier = Modifier.height(8.dp))

                    Button(
                        onClick = {
                            val today = LocalDate.now()
                            onMonthChange(YearMonth.from(today))
                            onDateSelected(today)
                        },
                        shape = RoundedCornerShape(50),
                        colors =
                        ButtonDefaults.buttonColors(
                            containerColor = MaterialTheme.colorScheme.primary,
                        ),
                        contentPadding = PaddingValues(horizontal = 20.dp, vertical = 8.dp),
                    ) {
                        Text(
                            text = "Today",
                            style = MaterialTheme.typography.labelLarge,
                            fontWeight = FontWeight.SemiBold,
                        )
                    }
                }
            }

            Spacer(modifier = Modifier.height(16.dp))

            Row(modifier = Modifier.fillMaxWidth()) {
                listOf("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat").forEach { day ->
                    Text(
                        text = day,
                        modifier = Modifier.weight(1f),
                        textAlign = TextAlign.Center,
                        style = MaterialTheme.typography.labelSmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                        fontWeight = FontWeight.Bold,
                    )
                }
            }

            Spacer(modifier = Modifier.height(8.dp))
        }

        items(numRows) { rowIndex ->
            Row(modifier = Modifier.fillMaxWidth()) {
                for (colIndex in 0 until 7) {
                    val index = rowIndex * 7 + colIndex
                    val dayNumber = index - firstDayOfWeek + 1

                    Box(modifier = Modifier.weight(1f)) {
                        if (dayNumber in 1..daysInMonth) {
                            val date = selectedMonth.atDay(dayNumber)
                            val sessionsOnDate = sessionsByDate[date] ?: emptyList()
                            val isSelected = date == selectedDate
                            val isToday = date == LocalDate.now()

                            CalendarDay(
                                day = dayNumber,
                                hasSession = sessionsOnDate.isNotEmpty(),
                                isSelected = isSelected,
                                isToday = isToday,
                                onClick = {
                                    if (sessionsOnDate.isNotEmpty()) {
                                        onDateSelected(if (isSelected) null else date)
                                    }
                                },
                            )
                        } else {
                            Spacer(modifier = Modifier.aspectRatio(1f))
                        }
                    }
                }
            }
        }

        if (selectedDate != null) {
            val sessionsOnSelectedDate = sessionsByDate[selectedDate] ?: emptyList()

            item {
                Spacer(modifier = Modifier.height(16.dp))

                Text(
                    text =
                    "Sessions on ${selectedDate.format(DateTimeFormatter.ofPattern("MMMM d, yyyy"))}",
                    style = MaterialTheme.typography.titleSmall,
                    fontWeight = FontWeight.Bold,
                    modifier = Modifier.padding(vertical = 8.dp),
                )
            }

            items(sessionsOnSelectedDate) { session ->
                SessionCard(
                    session = session,
                    gymName = gyms.find { it.id == session.gymId }?.name ?: "Unknown Gym",
                    onClick = { onNavigateToSessionDetail(session.id) },
                )
                Spacer(modifier = Modifier.height(8.dp))
            }

            item { Spacer(modifier = Modifier.height(16.dp)) }
        }
    }
}

@Composable
fun CalendarDay(
    day: Int,
    hasSession: Boolean,
    isSelected: Boolean,
    isToday: Boolean,
    onClick: () -> Unit,
) {
    Box(
        modifier =
        Modifier.aspectRatio(1f)
            .padding(2.dp)
            .clip(CircleShape)
            .background(
                when {
                    isSelected -> MaterialTheme.colorScheme.primaryContainer
                    isToday -> MaterialTheme.colorScheme.secondaryContainer
                    else -> Color.Transparent
                },
            )
            .clickable(enabled = hasSession, onClick = onClick),
        contentAlignment = Alignment.Center,
    ) {
        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Text(
                text = day.toString(),
                style = MaterialTheme.typography.bodyMedium,
                color =
                when {
                    isSelected -> MaterialTheme.colorScheme.onPrimaryContainer
                    isToday -> MaterialTheme.colorScheme.onSecondaryContainer
                    !hasSession -> MaterialTheme.colorScheme.onSurfaceVariant
                    else -> MaterialTheme.colorScheme.onSurface
                },
                fontWeight = if (hasSession || isToday) FontWeight.Bold else FontWeight.Normal,
            )

            if (hasSession) {
                Box(
                    modifier =
                    Modifier.size(6.dp)
                        .clip(CircleShape)
                        .background(
                            if (isSelected) {
                                MaterialTheme.colorScheme.primary
                            } else {
                                MaterialTheme.colorScheme.primary.copy(
                                    alpha = 0.7f,
                                )
                            },
                        ),
                )
            }
        }
    }
}
