import SwiftUI
import VoiceCatCore

struct ChannelEditView: View {
    let channelId: UInt32?
    @Bindable var session: SessionState
    @Environment(\.dismiss) private var dismiss

    // General
    @State private var name = ""
    @State private var topic = ""
    @State private var parentId: UInt32 = 0
    @State private var passwordProtected = false
    @State private var password = ""
    @State private var maxUsers = "0"
    @State private var sortOrder = "0"

    // Audio (Opus). Note: the channel list does not carry the current audio config, so when
    // editing an existing channel these start from the codec defaults (same as macOS/Windows).
    @State private var stereo = false
    @State private var bitrate = "64000"
    @State private var sampleRate = "48000"
    @State private var frameMs: UInt32 = 20
    @State private var application: UInt32 = 0
    @State private var packetLoss = "5"
    @State private var complexity = 10
    @State private var fec = true
    @State private var dtx = false
    @State private var dred = false

    private var isEditing: Bool { channelId != nil }

    var body: some View {
        NavigationStack {
            Form {
                Section("Channel Info") {
                    TextField("Name", text: $name)
                        .autocorrectionDisabled()
                        .accessibilityLabel("Channel name")
                    TextField("Topic (optional)", text: $topic)
                        .accessibilityLabel("Channel topic, optional")
                    Picker("Parent", selection: $parentId) {
                        Text("(root)").tag(UInt32(0))
                        ForEach(parentOptions) { ch in
                            Text(ch.name).tag(ch.id)
                        }
                    }
                    .accessibilityLabel("Parent channel")
                    Toggle("Password protected", isOn: $passwordProtected)
                    if passwordProtected {
                        SecureField("Password (blank keeps existing)", text: $password)
                            .accessibilityLabel("Channel password")
                    }
                    TextField("Max users (0 = unlimited)", text: $maxUsers)
                        .keyboardType(.numberPad)
                        .accessibilityLabel("Maximum users, zero means unlimited")
                    TextField("Sort order", text: $sortOrder)
                        .keyboardType(.numberPad)
                        .accessibilityLabel("Sort order")
                }

                Section("Audio (Opus)") {
                    Toggle("Stereo", isOn: $stereo)
                    TextField("Bitrate (bps)", text: $bitrate)
                        .keyboardType(.numberPad)
                        .accessibilityLabel("Bitrate in bits per second")
                    TextField("Sample rate (Hz)", text: $sampleRate)
                        .keyboardType(.numberPad)
                        .accessibilityLabel("Sample rate in Hz")
                    Picker("Frame", selection: $frameMs) {
                        ForEach([UInt32(10), 20, 40, 60], id: \.self) { ms in
                            Text("\(ms) ms").tag(ms)
                        }
                    }
                    .accessibilityLabel("Opus frame duration")
                    Picker("Application", selection: $application) {
                        Text("VoIP").tag(UInt32(0))
                        Text("Audio").tag(UInt32(1))
                        Text("Low delay").tag(UInt32(2))
                    }
                    .accessibilityLabel("Opus application profile")
                    TextField("Expected packet loss %", text: $packetLoss)
                        .keyboardType(.numberPad)
                        .accessibilityLabel("Expected packet loss percent, 0 to 100")
                    Stepper("Complexity: \(complexity)", value: $complexity, in: 0...10)
                        .accessibilityLabel("Opus complexity, 0 to 10")
                    Toggle("FEC (forward error correction)", isOn: $fec)
                    Toggle("DTX (discontinuous transmission)", isOn: $dtx)
                    Toggle("DRED (deep redundancy)", isOn: $dred)
                }
            }
            .navigationTitle(isEditing ? "Edit Channel" : "New Channel")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Save") {
                        save()
                        dismiss()
                    }
                    .disabled(name.trimmingCharacters(in: .whitespaces).isEmpty)
                }
            }
            .onAppear(perform: loadIfEditing)
        }
    }

    /// Channels offered as a parent. Excludes the channel being edited so it can't parent itself.
    private var parentOptions: [Channel] {
        session.channels
            .filter { $0.id != channelId }
            .sorted { $0.name < $1.name }
    }

    private func loadIfEditing() {
        guard let id = channelId,
              let ch = session.channels.first(where: { $0.id == id }) else { return }
        name = ch.name
        topic = ch.topic
        parentId = ch.parentId
        passwordProtected = ch.passwordProtected
        maxUsers = "\(ch.maxUsers)"
    }

    private func save() {
        let trimmedName = name.trimmingCharacters(in: .whitespaces)
        guard !trimmedName.isEmpty else { return }

        let audio = AudioConfig(
            stereo: stereo,
            sampleRate: UInt32(sampleRate) ?? 48000,
            bitrateBps: UInt32(bitrate) ?? 64000,
            frameMs: frameMs,
            application: application,
            fec: fec,
            expectedPacketLoss: min(UInt32(packetLoss) ?? 5, 100),
            dtx: dtx,
            complexity: UInt32(complexity),
            dred: dred
        )

        let pw: String? = passwordProtected ? (password.isEmpty ? nil : password) : nil
        let info = ChannelEdit(
            id: channelId ?? 0,
            parentId: parentId,
            name: trimmedName,
            topic: topic,
            passwordProtected: passwordProtected,
            password: pw,
            maxUsers: UInt32(maxUsers) ?? 0,
            sortOrder: UInt32(sortOrder) ?? 0,
            audio: audio
        )

        if isEditing {
            session.editChannel(info)
        } else {
            session.createChannel(info)
        }
    }
}
