import SwiftUI
import NucleicProtocol

/// The phone's fleet activity feed (mesh casting): notable events from every Mac and runner —
/// finished/needs-input turns, approvals, ships, transfers, dispatches — merged across origins
/// and surviving late joins (an hour-later app open replays the gap). A passive history
/// surface: it never alerts; rows deep-link to their session via the notification route.
///
/// `RecentActivitySection` is the Home dashboard's three-row peek; `ActivityFeedListView` is
/// the pushed full list.
struct RecentActivitySection: View {
    @EnvironmentObject var store: RemoteStore

    var body: some View {
        if !store.activityFeed.isEmpty {
            VStack(alignment: .leading, spacing: 10) {
                HStack {
                    Label("Recent activity", systemImage: "bell")
                        .font(.headline)
                    Spacer()
                    NavigationLink {
                        ActivityFeedListView()
                    } label: {
                        Text("See all")
                            .font(.subheadline)
                    }
                }
                VStack(spacing: 0) {
                    ForEach(store.activityFeed.suffix(3).reversed()) { item in
                        ActivityFeedRow(item: item)
                        if item.id != store.activityFeed.suffix(3).first?.id {
                            Divider().padding(.leading, 30)
                        }
                    }
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .card()
            .onAppear { store.markFeedSeen() }
        }
    }
}

struct ActivityFeedListView: View {
    @EnvironmentObject var store: RemoteStore

    var body: some View {
        List(store.activityFeed.reversed()) { item in
            ActivityFeedRow(item: item)
                .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
        }
        .listStyle(.plain)
        .navigationTitle("Activity")
        .navigationBarTitleDisplayMode(.inline)
        .overlay {
            if store.activityFeed.isEmpty {
                ContentUnavailableView(
                    "No fleet activity yet", systemImage: "bell.slash",
                    description: Text("Finished chats, approvals, ships, and transfers from every Mac and runner land here."))
            }
        }
        .onAppear { store.markFeedSeen() }
    }
}

private struct ActivityFeedRow: View {
    @EnvironmentObject var store: RemoteStore
    let item: ActivityFeedItem

    private var event: FeedEvent { item.event }

    var body: some View {
        Button {
            // Route like a notification tap: jump to the Sessions tab and push the session on
            // its owning host (works for any mesh host's session the phone mirrors).
            store.route(to: event.sessionID)
        } label: {
            HStack(alignment: .top, spacing: 10) {
                Image(systemName: ActivityFeedIcon.icon(for: event.kind))
                    .foregroundStyle(ActivityFeedIcon.tint(for: event.kind))
                    .font(.subheadline)
                    .frame(width: 20)
                    .padding(.top, 2)
                VStack(alignment: .leading, spacing: 2) {
                    HStack(spacing: 6) {
                        Text(event.sessionTitle.isEmpty ? "Untitled chat" : event.sessionTitle)
                            .font(.subheadline.weight(.medium))
                            .foregroundStyle(.primary)
                            .lineLimit(1)
                        Spacer(minLength: 4)
                        Text(event.at, format: .relative(presentation: .named))
                            .font(.caption2)
                            .foregroundStyle(.tertiary)
                    }
                    Text(subtitle)
                        .font(.caption)
                        .foregroundStyle(.secondary)
                        .lineLimit(2)
                }
            }
            .padding(.vertical, 6)
            .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
    }

    private var subtitle: String {
        var parts: [String] = [ActivityFeedIcon.headline(for: event)]
        if !event.projectName.isEmpty { parts.append(event.projectName) }
        if !event.hostName.isEmpty { parts.append(event.hostName) }
        return parts.joined(separator: " · ")
    }
}

/// The shared icon / tint / headline vocabulary for a fleet-activity `FeedEvent`, used by both the
/// activity feed rows and the Mesh Info screen's event log so they read identically.
enum ActivityFeedIcon {
    static func headline(for event: FeedEvent) -> String {
        switch event.kind {
        case .finished: "Finished"
        case .needsInput: "Waiting for you"
        case .needsApproval: event.detail.map { "Needs approval: \($0)" } ?? "Needs approval"
        case .shipped: event.detail.map { "Shipped · \($0)" } ?? "Shipped"
        case .transferredOut: "Moved to \(event.counterpartHostName ?? "another Mac")"
        case .transferredIn: "Arrived from \(event.counterpartHostName ?? "another Mac")"
        case .error: event.detail.map { "Error: \($0)" } ?? "Error"
        case .dispatched: "Dispatched here via Mesh"
        default: event.kind.rawValue  // a newer build's kind — render generically, never drop
        }
    }

    static func icon(for kind: FeedEvent.Kind) -> String {
        switch kind {
        case .finished: "checkmark.circle"
        case .needsInput: "bubble.left.and.exclamationmark.bubble.right"
        case .needsApproval: "hand.raised"
        case .shipped: "arrow.triangle.merge"
        case .transferredOut: "arrow.up.right.square"
        case .transferredIn: "arrow.down.left.square"
        case .error: "exclamationmark.triangle"
        case .dispatched: "paperplane"
        default: "circle"
        }
    }

    static func tint(for kind: FeedEvent.Kind) -> Color {
        switch kind {
        case .finished, .shipped: .green
        case .needsInput, .needsApproval: .orange
        case .error: .red
        default: .secondary
        }
    }
}
