import SwiftUI
import VoiceCatCore

// ChannelNode wraps Channel for OutlineGroup; childrenOrNil must be nil (not empty [])
// for leaf channels so OutlineGroup doesn't render expand buttons.
struct ChannelNode: Identifiable {
    let channel: Channel
    let children: [ChannelNode]?
    var id: UInt32 { channel.id }
}

struct ChannelTreeView: View {
    @Bindable var session: SessionState
    @State private var showCreateChannel = false
    @State private var editChannel: Channel?
    @State private var channelPassword = ""
    @State private var passwordChannelId: UInt32?

    var body: some View {
        List(channelTree, children: \.children) { node in
            ChannelRowView(node: node, session: session)
                .onTapGesture {
                    if node.channel.passwordProtected {
                        passwordChannelId = node.channel.id
                    } else {
                        session.joinChannel(node.channel.id)
                    }
                }
                .swipeActions(edge: .trailing) {
                    if session.permissions.isAdmin {
                        Button(role: .destructive) {
                            session.deleteChannel(node.channel.id)
                        } label: {
                            Label("Delete", systemImage: "trash")
                        }
                    }
                }
                .swipeActions(edge: .leading) {
                    if session.permissions.isAdmin {
                        Button {
                            editChannel = node.channel
                        } label: {
                            Label("Edit", systemImage: "pencil")
                        }
                        .tint(.blue)
                    }
                }
        }
        .listStyle(.sidebar)
        .toolbar {
            if session.permissions.canCreateTempChannel || session.permissions.isAdmin {
                ToolbarItem(placement: .primaryAction) {
                    Button {
                        showCreateChannel = true
                    } label: {
                        Image(systemName: "plus")
                    }
                    .accessibilityLabel("Create channel")
                }
            }
            if session.currentChannelId != 0 {
                ToolbarItem(placement: .topBarLeading) {
                    Button("Leave", systemImage: "arrow.left.circle") {
                        session.leaveChannel()
                    }
                    .accessibilityLabel("Leave current channel")
                }
            }
        }
        .sheet(isPresented: $showCreateChannel) {
            ChannelEditView(channelId: nil, session: session)
        }
        .sheet(item: $editChannel) { ch in
            ChannelEditView(channelId: ch.id, session: session)
        }
        .alert("Channel Password", isPresented: Binding(
            get: { passwordChannelId != nil },
            set: { if !$0 { passwordChannelId = nil; channelPassword = "" } }
        )) {
            SecureField("Password", text: $channelPassword)
                .accessibilityLabel("Channel password")
            Button("Join") {
                if let cid = passwordChannelId {
                    session.joinChannel(cid, password: channelPassword)
                }
                passwordChannelId = nil
                channelPassword = ""
            }
            Button("Cancel", role: .cancel) {
                passwordChannelId = nil
                channelPassword = ""
            }
        }
    }

    private var channelTree: [ChannelNode] {
        buildTree(parentId: 0, channels: session.channels)
    }

    private func buildTree(parentId: UInt32, channels: [Channel]) -> [ChannelNode] {
        channels
            .filter { $0.parentId == parentId }
            .map { ch in
                let kids = buildTree(parentId: ch.id, channels: channels)
                return ChannelNode(channel: ch, children: kids.isEmpty ? nil : kids)
            }
            .sorted { $0.channel.name < $1.channel.name }
    }
}

private struct ChannelRowView: View {
    let node: ChannelNode
    let session: SessionState

    var body: some View {
        let ch = node.channel
        let isCurrent = session.currentChannelId == ch.id
        let usersHere = session.users.filter { $0.channelId == ch.id }

        HStack(spacing: 8) {
            Image(systemName: ch.passwordProtected ? "lock.fill" : "number")
                .foregroundStyle(isCurrent ? .blue : .secondary)
                .imageScale(.small)
            VStack(alignment: .leading, spacing: 1) {
                Text(ch.name)
                    .fontWeight(isCurrent ? .semibold : .regular)
                if !ch.topic.isEmpty {
                    Text(ch.topic)
                        .font(.caption2)
                        .foregroundStyle(.secondary)
                        .lineLimit(1)
                }
            }
            Spacer()
            if !usersHere.isEmpty {
                Text("\(usersHere.count)")
                    .font(.caption)
                    .foregroundStyle(.secondary)
                    .accessibilityLabel("\(usersHere.count) users")
            }
        }
        .accessibilityElement(children: .combine)
        .accessibilityLabel("\(ch.name)\(isCurrent ? ", current" : "")\(ch.passwordProtected ? ", password protected" : "")\(!usersHere.isEmpty ? ", \(usersHere.count) users" : "")")
    }
}
