import SwiftUI
import NucleicProtocol

/// The to-do inbox (mirrors the Mac's idea inbox): capture ideas, group by project, then
/// complete, dispatch (start an agent), or delete each — all control scope.
struct TodosView: View {
    @EnvironmentObject var store: RemoteStore
    @State private var draft = ""

    private var open: [WireTodo] { store.dashboard.todos.filter { $0.status != .done } }

    /// Group open todos by project name ("Unassigned" bucket last).
    private var groups: [(name: String, todos: [WireTodo])] {
        let byProject = Dictionary(grouping: open) { $0.projectName ?? "Unassigned" }
        return byProject
            .map { ($0.key, $0.value.sorted { $0.updatedAt > $1.updatedAt }) }
            .sorted { ($0.name == "Unassigned" ? "zzz" : $0.name) < ($1.name == "Unassigned" ? "zzz" : $1.name) }
    }

    var body: some View {
        NavigationStack {
            List {
                Section {
                    HStack {
                        TextField("Capture an idea…", text: $draft)
                            .textFieldStyle(.roundedBorder)
                            .onSubmit(capture)
                            .keyboardDismissable()
                        Button(action: capture) { Image(systemName: "plus.circle.fill").font(.title3) }
                            .disabled(draft.trimmingCharacters(in: .whitespaces).isEmpty || !store.canControl)
                    }
                }
                if open.isEmpty {
                    ContentUnavailableView("Inbox zero", systemImage: "checkmark.circle",
                        description: Text("Capture an idea above to dispatch later."))
                }
                ForEach(groups, id: \.name) { group in
                    Section(group.name.uppercased()) {
                        ForEach(group.todos) { todo in TodoRow(todo: todo) }
                    }
                }
            }
            .navigationTitle("To-dos")
            .scrollDismissesKeyboard(.interactively)
            .refreshable { store.refreshSessions() }
        }
    }

    private func capture() {
        store.captureTodo(draft, projectID: nil)
        draft = ""
    }
}

private struct TodoRow: View {
    @EnvironmentObject var store: RemoteStore
    let todo: WireTodo

    var body: some View {
        HStack(spacing: 10) {
            Button { store.completeTodo(todo.id) } label: {
                Image(systemName: todo.status == .dispatched ? "circle.dashed" : "circle")
                    .foregroundStyle(.secondary)
            }.buttonStyle(.plain)
            VStack(alignment: .leading, spacing: 2) {
                Text(todo.summary?.isEmpty == false ? todo.summary! : todo.text)
                    .font(.subheadline).lineLimit(2)
                HStack(spacing: 6) {
                    if let triage = todo.triage {
                        TriageBadge(rawLevel: triage)
                    }
                    if todo.status == .dispatched {
                        Text("Dispatched").font(.caption2).foregroundStyle(Palette.active)
                    }
                }
            }
            Spacer()
            dispatchButton
        }
        .swipeActions {
            Button(role: .destructive) { store.deleteTodo(todo.id) } label: {
                Label("Delete", systemImage: "trash")
            }
        }
    }

    /// Dispatch to the todo's project, or pick one if unassigned.
    @ViewBuilder
    private var dispatchButton: some View {
        if todo.status == .open && store.canControl {
            if let pid = todo.projectID {
                Button { store.dispatchTodo(todo.id, in: pid) } label: {
                    Image(systemName: "play.circle.fill").foregroundStyle(Palette.accent)
                }.buttonStyle(.plain)
            } else if !store.dashboard.projects.isEmpty {
                Menu {
                    ForEach(store.dashboard.projects) { project in
                        Button(project.name) { store.dispatchTodo(todo.id, in: project.id) }
                    }
                } label: {
                    Image(systemName: "play.circle").foregroundStyle(Palette.accent)
                }
            }
        }
    }
}

/// A small colored badge showing an idea's triage level — the Mac's `TriageBadge`, fed by
/// the wire's raw level name. Honors the encouraging/classic labeling setting (same storage
/// key as the Mac); an unrecognized level from a newer host renders no badge.
struct TriageBadge: View {
    let rawLevel: String
    @AppStorage("nucleic.triageEncouragingLabels") private var encouraging = true

    private var label: String? {
        switch (rawLevel, encouraging) {
        case ("critical", true): "Max Impact"
        case ("high", true): "High Impact"
        case ("medium", true): "Worthwhile"
        case ("low", true): "Someday"
        case ("critical", false): "Critical"
        case ("high", false): "High"
        case ("medium", false): "Medium"
        case ("low", false): "Low"
        default: nil
        }
    }

    /// The Mac's badge hues: a red→orange→yellow→gray urgency scale for classic labels, a
    /// magenta→blue→green→slate reward scale for the encouraging framing.
    private var tint: Color? {
        switch (rawLevel, encouraging) {
        case ("critical", false): .red
        case ("high", false): .orange
        case ("medium", false): .yellow
        case ("low", false): .gray
        case ("critical", true): Color(red: 0.95, green: 0.33, blue: 0.78)  // vivid magenta
        case ("high", true): Color(red: 0.26, green: 0.54, blue: 1.00)      // bright blue
        case ("medium", true): Color(red: 0.18, green: 0.78, blue: 0.45)    // green
        case ("low", true): Color(red: 0.56, green: 0.60, blue: 0.67)       // calm slate
        default: nil
        }
    }

    var body: some View {
        if let label, let tint {
            HStack(spacing: 4) {
                Circle().fill(tint).frame(width: 7, height: 7)
                Text(label)
                    .font(.caption2.weight(.semibold))
                    .foregroundStyle(.secondary)
            }
            .padding(.horizontal, 7).padding(.vertical, 3)
            .background(tint.opacity(0.14), in: .capsule)
            .overlay(Capsule().strokeBorder(tint.opacity(0.35), lineWidth: 0.5))
            .fixedSize()
        }
    }
}
