import SwiftUI
import VoiceCatCore

/// One row of the combined chat/activity timeline. Mirrors the macOS/Windows clients, which
/// collapse chat messages and activity events into a single scrolling log (chat in normal
/// text, activity events in gray).
private enum TimelineItem: Identifiable {
    case message(ChatMessage)
    case activity(ActivityEntry)

    var id: UUID {
        switch self {
        case .message(let m): return m.id
        case .activity(let a): return a.id
        }
    }

    var timestamp: Date {
        switch self {
        case .message(let m): return m.timestamp
        case .activity(let a): return a.timestamp
        }
    }
}

struct ChatView: View {
    @Bindable var session: SessionState
    @State private var composeText = ""
    @State private var scope: VoiceCatTextScope = .channel
    @State private var privateTargetId: UInt32 = 0

    private var timeline: [TimelineItem] {
        let merged = session.messages.map(TimelineItem.message)
            + session.activityLog.map(TimelineItem.activity)
        return merged.sorted { $0.timestamp < $1.timestamp }
    }

    var body: some View {
        VStack(spacing: 0) {
            // Combined chat + activity timeline
            ScrollViewReader { proxy in
                ScrollView {
                    LazyVStack(alignment: .leading, spacing: 8) {
                        ForEach(timeline) { item in
                            switch item {
                            case .message(let msg):
                                ChatBubble(message: msg)
                                    .id(item.id)
                            case .activity(let entry):
                                ActivityRow(entry: entry)
                                    .id(item.id)
                            }
                        }
                    }
                    .padding()
                }
                .onChange(of: session.messages.count + session.activityLog.count) { _, _ in
                    if let last = timeline.last {
                        proxy.scrollTo(last.id, anchor: .bottom)
                    }
                }
            }

            Divider()

            // Compose bar
            HStack(spacing: 8) {
                TextField("Message…", text: $composeText, axis: .vertical)
                    .lineLimit(1...5)
                    .textFieldStyle(.roundedBorder)
                    .accessibilityLabel("Message text field")
                    .onSubmit { sendMessage() }

                Button {
                    sendMessage()
                } label: {
                    Image(systemName: "arrow.up.circle.fill")
                        .imageScale(.large)
                }
                .disabled(composeText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
                          || session.currentChannelId == 0)
                .accessibilityLabel("Send message")
            }
            .padding(.horizontal)
            .padding(.vertical, 8)
        }
        .navigationTitle("Chat")
        .navigationBarTitleDisplayMode(.inline)
    }

    private func sendMessage() {
        let text = composeText.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty else { return }
        session.sendText(text, scope: .channel, targetId: session.currentChannelId)
        composeText = ""
    }
}

private struct ChatBubble: View {
    let message: ChatMessage

    private var timeString: String {
        let fmt = DateFormatter()
        fmt.dateStyle = .none
        fmt.timeStyle = .short
        return fmt.string(from: message.timestamp)
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 2) {
            HStack(spacing: 4) {
                Text(message.senderName)
                    .font(.caption)
                    .fontWeight(.semibold)
                    .foregroundStyle(.secondary)
                Text(timeString)
                    .font(.caption2)
                    .foregroundStyle(.tertiary)
            }
            Text(message.text)
                .font(.body)
                .textSelection(.enabled)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .accessibilityElement(children: .combine)
        .accessibilityLabel("\(message.senderName) at \(timeString): \(message.text)")
    }
}

/// A compact, gray activity row interleaved into the chat timeline (joins/leaves, talk state,
/// streams, server mute, etc.). Matches the "activity = gray" convention of the macOS/Windows
/// unified logs.
private struct ActivityRow: View {
    let entry: ActivityEntry

    private static let timeFormatter: DateFormatter = {
        let fmt = DateFormatter()
        fmt.dateStyle = .none
        fmt.timeStyle = .short
        return fmt
    }()

    private var timeString: String { Self.timeFormatter.string(from: entry.timestamp) }

    var body: some View {
        HStack(alignment: .top, spacing: 6) {
            Text(timeString)
                .font(.caption2)
                .foregroundStyle(.tertiary)
                .monospacedDigit()
            Text(entry.text)
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .accessibilityElement(children: .combine)
        .accessibilityLabel("\(timeString): \(entry.text)")
    }
}
