import AppKit
import VoiceCatCore

final class ChannelEditSheet: NSViewController {

    var onComplete: ((ChannelEdit?) -> Void)?

    private let channels: [Channel]
    private var editing: ChannelEdit?

    private let nameField = NSTextField()
    private let topicField = NSTextField()
    private let parentPicker = NSPopUpButton()
    private let pwCheckbox = NSButton(checkboxWithTitle: "Password protected", target: nil, action: nil)
    private let pwField = NSSecureTextField()
    private let maxUsersField: NSTextField = {
        let f = NSTextField(); f.stringValue = "0"; return f
    }()
    private let sortOrderField: NSTextField = {
        let f = NSTextField(); f.stringValue = "0"; return f
    }()
    private let stereoCheckbox = NSButton(checkboxWithTitle: "Stereo", target: nil, action: nil)
    private let bitrateField: NSTextField = {
        let f = NSTextField(); f.stringValue = "64000"; return f
    }()
    private let fecCheckbox = NSButton(checkboxWithTitle: "FEC", target: nil, action: nil)
    private let dtxCheckbox = NSButton(checkboxWithTitle: "DTX", target: nil, action: nil)
    private let dredCheckbox = NSButton(checkboxWithTitle: "DRED", target: nil, action: nil)
    private let frameMsPicker = NSPopUpButton()
    private let applicationPicker = NSPopUpButton()
    private let sampleRateField: NSTextField = {
        let f = NSTextField(); f.stringValue = "48000"; return f
    }()
    private let packetLossField: NSTextField = {
        let f = NSTextField(); f.stringValue = "5"; return f
    }()
    private let complexityField: NSTextField = {
        let f = NSTextField(); f.stringValue = "10"; return f
    }()

    init(channels: [Channel], editing: ChannelEdit?) {
        self.channels = channels
        self.editing = editing
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) { fatalError() }

    override func loadView() {
        view = NSView(frame: NSRect(x: 0, y: 0, width: 440, height: 360))
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        buildUI()
        populateIfEditing()
    }

    private func buildUI() {
        let titleText = editing == nil ? "Create Channel" : "Edit Channel"
        let titleLabel = NSTextField(labelWithString: titleText)
        titleLabel.font = .boldSystemFont(ofSize: 13)

        nameField.placeholderString = "Channel name"
        nameField.setAccessibilityLabel("Channel name")
        topicField.placeholderString = "Topic (optional)"
        topicField.setAccessibilityLabel("Channel topic")

        parentPicker.addItem(withTitle: "(root)")
        parentPicker.menu?.items.last?.representedObject = nil as UInt32?
        for ch in channels.sorted(by: { $0.name < $1.name }) {
            let item = NSMenuItem(title: ch.name, action: nil, keyEquivalent: "")
            item.representedObject = ch.id
            parentPicker.menu?.addItem(item)
        }
        parentPicker.setAccessibilityLabel("Parent channel")

        pwCheckbox.target = self; pwCheckbox.action = #selector(pwToggled)
        pwField.placeholderString = "password (leave blank to keep existing)"
        pwField.setAccessibilityLabel("Channel password")
        pwField.isEnabled = false

        maxUsersField.setAccessibilityLabel("Max users (0 = unlimited)")
        sortOrderField.setAccessibilityLabel("Sort order")

        for ms in ["10", "20", "40", "60"] { frameMsPicker.addItem(withTitle: "\(ms) ms") }
        frameMsPicker.selectItem(withTitle: "20 ms")
        frameMsPicker.setAccessibilityLabel("Opus frame duration")

        applicationPicker.addItem(withTitle: "VoIP")
        applicationPicker.addItem(withTitle: "Audio")
        applicationPicker.addItem(withTitle: "Low delay")
        applicationPicker.setAccessibilityLabel("Opus application profile")

        fecCheckbox.state = .on
        stereoCheckbox.setAccessibilityLabel("Stereo audio")
        bitrateField.setAccessibilityLabel("Bitrate in bits per second")
        sampleRateField.setAccessibilityLabel("Sample rate in Hz")
        packetLossField.setAccessibilityLabel("Expected packet loss percent (0 to 100)")
        complexityField.setAccessibilityLabel("Opus complexity (0 to 10)")
        fecCheckbox.setAccessibilityLabel("Forward error correction")
        dtxCheckbox.setAccessibilityLabel("Discontinuous transmission")
        dredCheckbox.setAccessibilityLabel("Deep redundancy (DRED)")

        let generalGrid = NSGridView(views: [
            [NSTextField(labelWithString: "Name:"), nameField],
            [NSTextField(labelWithString: "Topic:"), topicField],
            [NSTextField(labelWithString: "Parent:"), parentPicker],
            [pwCheckbox, pwField],
            [NSTextField(labelWithString: "Max users:"), maxUsersField],
            [NSTextField(labelWithString: "Sort order:"), sortOrderField],
        ])
        generalGrid.rowSpacing = 8; generalGrid.columnSpacing = 8
        generalGrid.column(at: 0).xPlacement = .trailing

        let audioGrid = NSGridView(views: [
            [NSTextField(labelWithString: "Bitrate:"), bitrateField],
            [NSTextField(labelWithString: "Sample rate:"), sampleRateField],
            [NSTextField(labelWithString: "Frame:"), frameMsPicker],
            [NSTextField(labelWithString: "Application:"), applicationPicker],
            [NSTextField(labelWithString: "Packet loss %:"), packetLossField],
            [NSTextField(labelWithString: "Complexity:"), complexityField],
            [stereoCheckbox, fecCheckbox],
            [dtxCheckbox, dredCheckbox],
        ])
        audioGrid.rowSpacing = 8; audioGrid.columnSpacing = 8
        audioGrid.column(at: 0).xPlacement = .trailing

        let tabs = NSTabView()
        let generalTab = NSTabViewItem(identifier: "general")
        generalTab.label = "General"
        generalTab.view = generalGrid
        let audioTab = NSTabViewItem(identifier: "audio")
        audioTab.label = "Audio"
        audioTab.view = audioGrid
        tabs.addTabViewItem(generalTab)
        tabs.addTabViewItem(audioTab)

        let cancelButton = NSButton(title: "Cancel", target: self, action: #selector(cancelClicked))
        cancelButton.bezelStyle = .rounded
        let saveButton = NSButton(title: editing == nil ? "Create" : "Save",
                                  target: self, action: #selector(saveClicked))
        saveButton.bezelStyle = .rounded; saveButton.keyEquivalent = "\r"

        let buttonRow = NSStackView(views: [NSView(), cancelButton, saveButton])
        buttonRow.orientation = .horizontal; buttonRow.spacing = 8

        let stack = NSStackView(views: [titleLabel, tabs, buttonRow])
        stack.orientation = .vertical
        stack.spacing = 12
        stack.edgeInsets = NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
        stack.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stack)
        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: view.topAnchor),
            stack.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            stack.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            stack.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        ])
    }

    private func populateIfEditing() {
        guard let e = editing else { return }
        nameField.stringValue = e.name
        topicField.stringValue = e.topic
        if e.parentId != 0 {
            for item in parentPicker.itemArray where (item.representedObject as? UInt32) == e.parentId {
                parentPicker.select(item); break
            }
        }
        pwCheckbox.state = e.passwordProtected ? .on : .off
        pwField.isEnabled = e.passwordProtected
        maxUsersField.stringValue = "\(e.maxUsers)"
        sortOrderField.stringValue = "\(e.sortOrder)"
        stereoCheckbox.state = e.audio.stereo ? .on : .off
        bitrateField.stringValue = "\(e.audio.bitrateBps)"
        sampleRateField.stringValue = "\(e.audio.sampleRate)"
        packetLossField.stringValue = "\(e.audio.expectedPacketLoss)"
        complexityField.stringValue = "\(e.audio.complexity)"
        fecCheckbox.state = e.audio.fec ? .on : .off
        dtxCheckbox.state = e.audio.dtx ? .on : .off
        dredCheckbox.state = e.audio.dred ? .on : .off
        applicationPicker.selectItem(at: Int(min(e.audio.application, 2)))
        let frameStr = "\(e.audio.frameMs) ms"
        if let item = frameMsPicker.item(withTitle: frameStr) { frameMsPicker.select(item) }
    }

    @objc private func pwToggled() {
        pwField.isEnabled = pwCheckbox.state == .on
    }

    @objc private func saveClicked() {
        let name = nameField.stringValue.trimmingCharacters(in: .whitespaces)
        guard !name.isEmpty else { nameField.becomeFirstResponder(); return }

        let parentId = parentPicker.selectedItem?.representedObject as? UInt32 ?? 0
        let maxUsers = UInt32(maxUsersField.stringValue) ?? 0
        let sortOrder = UInt32(sortOrderField.stringValue) ?? 0
        let bitrate = UInt32(bitrateField.stringValue) ?? 64000
        let sampleRate = UInt32(sampleRateField.stringValue) ?? 48000
        let packetLoss = min(UInt32(packetLossField.stringValue) ?? 5, 100)
        let complexity = min(UInt32(complexityField.stringValue) ?? 10, 10)
        let frameMsStr = frameMsPicker.titleOfSelectedItem?.replacingOccurrences(of: " ms", with: "") ?? "20"
        let frameMs = UInt32(frameMsStr) ?? 20
        let application = UInt32(max(applicationPicker.indexOfSelectedItem, 0))

        let audio = AudioConfig(
            stereo: stereoCheckbox.state == .on,
            sampleRate: sampleRate,
            bitrateBps: bitrate,
            frameMs: frameMs,
            application: application,
            fec: fecCheckbox.state == .on,
            expectedPacketLoss: packetLoss,
            dtx: dtxCheckbox.state == .on,
            complexity: complexity,
            dred: dredCheckbox.state == .on
        )
        let pwProtected = pwCheckbox.state == .on
        let pw: String? = pwProtected ? (pwField.stringValue.isEmpty ? nil : pwField.stringValue) : nil

        let result = ChannelEdit(
            id: editing?.id ?? 0,
            parentId: parentId,
            name: name,
            topic: topicField.stringValue,
            passwordProtected: pwProtected,
            password: pw,
            maxUsers: maxUsers,
            sortOrder: sortOrder,
            audio: audio
        )
        dismiss(nil)
        onComplete?(result)
    }

    @objc private func cancelClicked() {
        dismiss(nil)
        onComplete?(nil)
    }
}
