// Copyright (C) 2026 Jason M. Schwefel. All Rights Reserved.
package com.coldboreballisticsllc.scopedope.ui.screens.dope

import android.net.Uri
import android.text.format.DateFormat
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
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.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Description
import androidx.compose.material.icons.filled.History
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.coldboreballisticsllc.scopedope.data.session.ImportResult
import com.coldboreballisticsllc.scopedope.data.session.RecentSession
import com.coldboreballisticsllc.scopedope.ui.session.SessionViewModel
import com.coldboreballisticsllc.scopedope.ui.theme.*
import java.io.File
import java.util.Date

private sealed class PendingLoad {
    data class FromRecent(val session: RecentSession) : PendingLoad()
    data class FromFile(val file: File) : PendingLoad()
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DopeFileBrowserSheet(
    sessionVm: SessionViewModel,
    onDismiss: () -> Unit,
) {
    val state       = sessionVm.state.collectAsState().value
    var dopeOnly    by remember { mutableStateOf(true) }
    var files       by remember { mutableStateOf(sessionVm.listDopeFiles(true)) }
    var pending     by remember { mutableStateOf<Pair<Uri, String>?>(null) }
    var pendingLoad by remember { mutableStateOf<PendingLoad?>(null) }

    fun refresh() { files = sessionVm.listDopeFiles(dopeOnly) }

    fun requestLoad(load: PendingLoad) {
        if (state.isDirty) {
            pendingLoad = load
        } else {
            when (load) {
                is PendingLoad.FromRecent -> { sessionVm.loadFromRecentSession(load.session); onDismiss() }
                is PendingLoad.FromFile   -> { sessionVm.loadSessionFromFile(load.file);      onDismiss() }
            }
        }
    }

    val importLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.OpenDocument()
    ) { uri ->
        if (uri == null) return@rememberLauncherForActivityResult
        val filename = sessionVm.resolveImportFilename(uri)
        when (val result = sessionVm.importDopeFile(uri, filename)) {
            is ImportResult.Success   -> { refresh(); sessionVm.loadSessionFromFile(result.file); onDismiss() }
            is ImportResult.Duplicate -> { pending = uri to filename }
            is ImportResult.Failure   -> { /* no-op: file unchanged */ }
        }
    }

    // Duplicate resolution dialog
    pending?.let { (uri, filename) ->
        AlertDialog(
            onDismissRequest = { pending = null },
            title            = { Text("File Already Exists", color = ColorTextPrimary) },
            text             = {
                Text(
                    "'$filename' is already in your ScopeDOPE library. Overwrite or keep both?",
                    color = ColorTextMuted,
                    style = MaterialTheme.typography.bodyMedium,
                )
            },
            confirmButton = {
                TextButton(onClick = {
                    val r = sessionVm.overwriteDopeFile(uri, filename)
                    pending = null
                    if (r is ImportResult.Success) { refresh(); sessionVm.loadSessionFromFile(r.file); onDismiss() }
                }) { Text("Overwrite", color = ColorAmber) }
            },
            dismissButton = {
                Row {
                    TextButton(onClick = { pending = null }) { Text("Cancel", color = ColorTextMuted) }
                    Spacer(Modifier.width(4.dp))
                    TextButton(onClick = {
                        val r = sessionVm.keepBothDopeFiles(uri, filename)
                        pending = null
                        if (r is ImportResult.Success) { refresh(); sessionVm.loadSessionFromFile(r.file); onDismiss() }
                    }) { Text("Keep Both", color = ColorAmberDim) }
                }
            },
            containerColor    = ColorSurface,
            titleContentColor = ColorTextPrimary,
        )
    }

    // Unsaved-changes confirmation dialog
    pendingLoad?.let { load ->
        val loadName = when (load) {
            is PendingLoad.FromRecent -> load.session.name
            is PendingLoad.FromFile   -> load.file.name
        }
        AlertDialog(
            onDismissRequest = { pendingLoad = null },
            title            = { Text("Unsaved Changes", color = ColorTextPrimary) },
            text             = {
                Text(
                    "You have unsaved changes. Load '$loadName' anyway?",
                    color = ColorTextMuted,
                    style = MaterialTheme.typography.bodyMedium,
                )
            },
            confirmButton = {
                TextButton(onClick = {
                    val l = pendingLoad
                    pendingLoad = null
                    when (l) {
                        is PendingLoad.FromRecent -> { sessionVm.loadFromRecentSession(l.session); onDismiss() }
                        is PendingLoad.FromFile   -> { sessionVm.loadSessionFromFile(l.file);      onDismiss() }
                        null -> {}
                    }
                }) { Text("Load Anyway", color = ColorAmber) }
            },
            dismissButton = {
                TextButton(onClick = { pendingLoad = null }) {
                    Text("Cancel", color = ColorTextMuted)
                }
            },
            containerColor    = ColorSurface,
            titleContentColor = ColorTextPrimary,
        )
    }

    ModalBottomSheet(
        onDismissRequest = onDismiss,
        containerColor   = ColorSurface,
        sheetState       = rememberModalBottomSheetState(skipPartiallyExpanded = true),
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .navigationBarsPadding()
                .padding(horizontal = 16.dp)
                .padding(bottom = 16.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp),
        ) {
            Text(
                text  = "Sessions",
                style = MaterialTheme.typography.titleMedium,
                color = ColorTextPrimary,
            )

            // ── Recent sessions ───────────────────────────────────────────────
            if (state.recentSessions.isNotEmpty()) {
                Row(
                    verticalAlignment     = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(6.dp),
                ) {
                    Icon(
                        imageVector        = Icons.Default.History,
                        contentDescription = null,
                        tint               = ColorTextMuted,
                        modifier           = Modifier.size(16.dp),
                    )
                    Text(
                        text  = "Recent",
                        style = MaterialTheme.typography.labelMedium,
                        color = ColorTextMuted,
                    )
                }
                LazyColumn(
                    modifier            = Modifier.heightIn(max = 200.dp),
                    verticalArrangement = Arrangement.spacedBy(2.dp),
                ) {
                    items(state.recentSessions, key = { it.filePath }) { session ->
                        RecentSessionRow(
                            session  = session,
                            onClick  = { requestLoad(PendingLoad.FromRecent(session)) },
                            onRemove = { sessionVm.removeFromRecentHistory(session.filePath) },
                        )
                    }
                }

                HorizontalDivider(color = ColorBorder)
            }

            // ── Library ───────────────────────────────────────────────────────
            Row(
                modifier              = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment     = Alignment.CenterVertically,
            ) {
                Text(
                    text  = "Library",
                    style = MaterialTheme.typography.labelMedium,
                    color = ColorTextMuted,
                )
                FilterChip(
                    selected = dopeOnly,
                    onClick  = {
                        val next = !dopeOnly
                        dopeOnly = next
                        files    = sessionVm.listDopeFiles(next)
                    },
                    label  = {
                        Text(
                            text  = if (dopeOnly) ".dope only" else "All files",
                            style = MaterialTheme.typography.labelSmall,
                        )
                    },
                    colors = FilterChipDefaults.filterChipColors(
                        selectedContainerColor = ColorAmber,
                        containerColor         = ColorSurface,
                        selectedLabelColor     = ColorBackground,
                        labelColor             = ColorTextMuted,
                    ),
                    border = FilterChipDefaults.filterChipBorder(
                        enabled             = true,
                        selected            = dopeOnly,
                        borderColor         = ColorBorder,
                        selectedBorderColor = ColorAmber,
                    ),
                )
            }

            if (files.isEmpty()) {
                Box(
                    modifier         = Modifier.fillMaxWidth().height(80.dp),
                    contentAlignment = Alignment.Center,
                ) {
                    Text(
                        text  = if (dopeOnly) "No .dope files in library yet.\nUse Import to add one."
                                else "Library is empty.",
                        style = MaterialTheme.typography.bodyMedium,
                        color = ColorTextMuted,
                    )
                }
            } else {
                LazyColumn(
                    modifier            = Modifier.heightIn(max = 240.dp),
                    verticalArrangement = Arrangement.spacedBy(2.dp),
                ) {
                    items(files, key = { it.absolutePath }) { file ->
                        FileRow(
                            file    = file,
                            onClick = { requestLoad(PendingLoad.FromFile(file)) },
                        )
                    }
                }
            }

            HorizontalDivider(color = ColorBorder)

            // ── Import button ─────────────────────────────────────────────────
            OutlinedButton(
                onClick  = {
                    importLauncher.launch(arrayOf(
                        "application/vnd.schwefel.scopedope+json",
                        "application/json",
                        "*/*",
                    ))
                },
                modifier = Modifier.fillMaxWidth(),
                colors   = ButtonDefaults.outlinedButtonColors(contentColor = ColorAmber),
                border   = androidx.compose.foundation.BorderStroke(1.dp, ColorAmber),
            ) {
                Text("Import from Downloads / Email", style = MaterialTheme.typography.labelMedium)
            }
        }
    }
}

@Composable
private fun RecentSessionRow(
    session:  RecentSession,
    onClick:  () -> Unit,
    onRemove: () -> Unit,
) {
    val dateStr = remember(session.timestampMs) {
        DateFormat.format("MMM d, yyyy  h:mm a", Date(session.timestampMs)).toString()
    }
    Row(
        modifier              = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
            .padding(vertical = 8.dp, horizontal = 4.dp),
        verticalAlignment     = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        Icon(
            imageVector        = Icons.Default.History,
            contentDescription = null,
            tint               = ColorAmberDim,
            modifier           = Modifier.size(20.dp),
        )
        Column(modifier = Modifier.weight(1f)) {
            Text(
                text  = session.name,
                style = MaterialTheme.typography.bodyMedium,
                color = ColorTextPrimary,
            )
            Text(
                text  = buildString {
                    if (session.caliber.isNotBlank()) { append(session.caliber); append("  ·  ") }
                    append(dateStr)
                },
                style = MaterialTheme.typography.labelSmall,
                color = ColorTextMuted,
            )
        }
        IconButton(
            onClick  = onRemove,
            modifier = Modifier.size(36.dp),
        ) {
            Icon(
                imageVector        = Icons.Default.Delete,
                contentDescription = "Remove from recents",
                tint               = ColorTextMuted,
                modifier           = Modifier.size(18.dp),
            )
        }
    }
}

@Composable
private fun FileRow(file: File, onClick: () -> Unit) {
    val dateStr = remember(file.lastModified()) {
        DateFormat.format("MMM d, yyyy", Date(file.lastModified())).toString()
    }
    Row(
        modifier              = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
            .padding(vertical = 10.dp, horizontal = 4.dp),
        verticalAlignment     = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        Icon(
            imageVector        = Icons.Default.Description,
            contentDescription = null,
            tint               = ColorAmberDim,
            modifier           = Modifier.size(20.dp),
        )
        Column(modifier = Modifier.weight(1f)) {
            Text(
                text  = file.name,
                style = MaterialTheme.typography.bodyMedium,
                color = ColorTextPrimary,
            )
            Text(
                text  = dateStr,
                style = MaterialTheme.typography.labelSmall,
                color = ColorTextMuted,
            )
        }
    }
}
