import SwiftUI

struct WidgetView: View {
    let formId: String
    let widget: WidgetState
    @Environment(ConnectionManager.self) private var manager

    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            switch widget.type {
            case .button:
                Button {
                    manager.sendFormEvent(
                        formId: formId, widgetId: widget.id,
                        eventType: .buttonClicked
                    )
                } label: {
                    Text(widget.label)
                        .frame(maxWidth: .infinity)
                }
                .buttonStyle(.borderedProminent)
                .disabled(!widget.enabled)

            case .textField:
                TextFieldWidget(formId: formId, widget: widget)

            case .checkBox:
                Toggle(widget.label, isOn: Bindable(widget).isChecked)
                    .disabled(!widget.enabled)
                    .onChange(of: widget.isChecked) { _, newValue in
                        manager.sendFormEvent(
                            formId: formId, widgetId: widget.id,
                            eventType: .checkBoxValueChanged,
                            value: .bool(newValue)
                        )
                    }

            case .listBox:
                ListBoxContent(formId: formId, widget: widget)

            case .slider:
                SliderWidget(formId: formId, widget: widget)

            case .treeView:
                TreeViewWidget(formId: formId, widget: widget)

            case .multiSelectList:
                MultiSelectContent(formId: formId, widget: widget)
            }
        }
    }
}

private struct TextFieldWidget: View {
    let formId: String
    let widget: WidgetState
    @Environment(ConnectionManager.self) private var manager

    var body: some View {
        if !widget.label.isEmpty {
            Text(widget.label)
                .font(.headline)
        }
        if widget.readOnly {
            Text(widget.text)
                .foregroundStyle(.secondary)
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(8)
                .background(.quaternary)
                .clipShape(.rect(cornerRadius: 8))
        } else if widget.isPassword {
            SecureField(widget.label, text: Bindable(widget).text)
                .textFieldStyle(.roundedBorder)
                .disabled(!widget.enabled)
                .onChange(of: widget.text) { _, newValue in
                    enforceMaxLength(newValue)
                    sendTextChanged(newValue)
                }
                .onSubmit { sendTextSubmitted() }
        } else {
            TextField(widget.label, text: Bindable(widget).text)
                .textFieldStyle(.roundedBorder)
                .disabled(!widget.enabled)
                .onChange(of: widget.text) { _, newValue in
                    enforceMaxLength(newValue)
                    sendTextChanged(newValue)
                }
                .onSubmit { sendTextSubmitted() }
        }
    }

    private func enforceMaxLength(_ text: String) {
        if text.count > widget.maxLength {
            widget.text = String(text.prefix(widget.maxLength))
        }
    }

    private func sendTextChanged(_ text: String) {
        manager.sendFormEvent(
            formId: formId, widgetId: widget.id,
            eventType: .textChanged,
            value: .string(text)
        )
    }

    private func sendTextSubmitted() {
        manager.sendFormEvent(
            formId: formId, widgetId: widget.id,
            eventType: .textSubmitted,
            value: .string(widget.text)
        )
    }
}

private struct SliderWidget: View {
    let formId: String
    let widget: WidgetState
    @Environment(ConnectionManager.self) private var manager

    var body: some View {
        if !widget.label.isEmpty {
            Text(widget.label)
                .font(.headline)
        }
        LabeledContent(widget.label) {
            Slider(
                value: Binding(
                    get: { Double(widget.sliderValue) },
                    set: { widget.sliderValue = Int($0) }
                ),
                in: Double(widget.minValue)...Double(widget.maxValue),
                step: Double(widget.increment)
            )
            .disabled(!widget.enabled)
            .onChange(of: widget.sliderValue) { _, newValue in
                manager.sendFormEvent(
                    formId: formId, widgetId: widget.id,
                    eventType: .sliderMoved,
                    value: .uint(UInt64(newValue))
                )
            }
        }
    }
}

private struct TreeViewWidget: View {
    let formId: String
    let widget: WidgetState
    @Environment(ConnectionManager.self) private var manager

    var body: some View {
        if !widget.label.isEmpty {
            Text(widget.label)
                .font(.headline)
        }
        ForEach(widget.nodes) { node in
            TreeNodeView(
                node: node, formId: formId,
                widgetId: widget.id, depth: 0
            )
        }
    }
}
