import OpenClawKit
import SwiftUI

struct GatewayQuickSetupSheet: View {
    @Environment(NodeAppModel.self) private var appModel
    @Environment(GatewayConnectionController.self) private var gatewayController
    @Environment(\.dismiss) private var dismiss

    @AppStorage("onboarding.quickSetupDismissed") private var quickSetupDismissed: Bool = false
    @State private var connecting: Bool = false
    @State private var connectError: String?
    @State private var showGatewayProblemDetails: Bool = false

    var body: some View {
        NavigationStack {
            VStack(alignment: .leading, spacing: 16) {
                Text("Connect to a Gateway?")
                    .font(OpenClawType.title2)

                if let gatewayProblem = self.appModel.lastGatewayProblem {
                    GatewayProblemBanner(
                        problem: gatewayProblem,
                        primaryActionTitle: self.gatewayProblemPrimaryActionTitle(gatewayProblem),
                        onPrimaryAction: {
                            Task { await self.handleGatewayProblemPrimaryAction(gatewayProblem) }
                        },
                        onShowDetails: {
                            self.showGatewayProblemDetails = true
                        })
                }

                if let candidate = self.bestCandidate {
                    GatewayQuickSetupCandidatePanel(
                        name: candidate.name,
                        debugID: candidate.debugID,
                        discoveryStatusText: self.gatewayController.discoveryStatusText,
                        gatewayDisplayStatusText: self.appModel.gatewayDisplayStatusText,
                        nodeStatusText: self.appModel.nodeStatusText,
                        operatorStatusText: self.appModel.operatorStatusText)

                    Button {
                        self.connectError = nil
                        self.connecting = true
                        Task {
                            let err = await self.gatewayController.connectWithDiagnostics(candidate)
                            await MainActor.run {
                                self.connecting = false
                                self.connectError = err
                            }
                        }
                    } label: {
                        Group {
                            if self.connecting {
                                HStack(spacing: 8) {
                                    ProgressView().progressViewStyle(.circular)
                                    Text("Connecting…")
                                        .font(OpenClawType.headline)
                                }
                            } else {
                                Text("Connect")
                                    .font(OpenClawType.headline)
                            }
                        }
                    }
                    .font(OpenClawType.headline)
                    .openClawPrimaryButton()
                    .disabled(self.connecting)

                    if let connectError {
                        Text(connectError)
                            .font(OpenClawType.footnote)
                            .foregroundStyle(.secondary)
                            .textSelection(.enabled)
                    }

                    Button {
                        self.dismiss()
                    } label: {
                        Text("Not now")
                            .font(OpenClawType.headline)
                    }
                    .font(OpenClawType.headline)
                    .openClawSecondaryButton()
                    .disabled(self.connecting)

                    self.fullRowToggle("Don’t show this again", isOn: self.$quickSetupDismissed)
                        .padding(.top, 4)
                } else {
                    Text("No gateways found yet. Make sure your gateway is running and Bonjour discovery is enabled.")
                        .font(OpenClawType.subhead)
                        .foregroundStyle(.secondary)
                }

                Spacer()
            }
            .font(OpenClawType.body)
            .padding()
            .navigationTitle("Quick Setup")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .principal) {
                    Text("Quick Setup")
                        .font(OpenClawType.headline)
                }
                ToolbarItem(placement: .topBarTrailing) {
                    Button {
                        self.quickSetupDismissed = true
                        self.dismiss()
                    } label: {
                        Text("Close")
                            .font(OpenClawType.subheadSemiBold)
                    }
                    .font(OpenClawType.subheadSemiBold)
                }
            }
        }
        .sheet(isPresented: self.$showGatewayProblemDetails) {
            if let gatewayProblem = self.appModel.lastGatewayProblem {
                GatewayProblemDetailsSheet(
                    problem: gatewayProblem,
                    primaryActionTitle: self.gatewayProblemPrimaryActionTitle(gatewayProblem),
                    onPrimaryAction: {
                        Task { await self.handleGatewayProblemPrimaryAction(gatewayProblem) }
                    })
            }
        }
    }

    private var bestCandidate: GatewayDiscoveryModel.DiscoveredGateway? {
        // Prefer whatever discovery says is first; the list is already name-sorted.
        self.gatewayController.gateways.first
    }

    private func fullRowToggle(_ title: LocalizedStringKey, isOn: Binding<Bool>) -> some View {
        Toggle(isOn: isOn) {
            Text(title)
                .font(OpenClawType.subhead)
        }
        .font(OpenClawType.subhead)
        .contentShape(Rectangle())
        .overlay {
            // Keep Toggle semantics for accessibility while making the full visual row tappable.
            Button {
                isOn.wrappedValue.toggle()
            } label: {
                Rectangle()
                    .fill(.clear)
                    .contentShape(Rectangle())
            }
            .font(OpenClawType.subhead)
            .buttonStyle(.plain)
            .accessibilityHidden(true)
        }
    }

    private func gatewayProblemPrimaryActionTitle(_ problem: GatewayConnectionProblem) -> String? {
        GatewayProblemPrimaryAction.title(for: problem, retryTitle: "Connect")
    }

    private func handleGatewayProblemPrimaryAction(_ problem: GatewayConnectionProblem) async {
        if problem.canTrustRotatedCertificate {
            _ = await self.gatewayController.trustRotatedGatewayCertificate(from: problem)
            return
        }
        if GatewayProblemPrimaryAction.openProtocolMismatchHelpIfNeeded(problem) {
            return
        }
        guard problem.retryable else { return }
        guard let candidate = self.bestCandidate else { return }
        self.connectError = nil
        self.connecting = true
        let err = await self.gatewayController.connectWithDiagnostics(candidate)
        self.connecting = false
        self.connectError = err
    }
}

private struct GatewayQuickSetupCandidatePanel: View {
    private static let readableMonospaceWidth: CGFloat = 72 * 8

    let name: String
    let debugID: String
    let discoveryStatusText: String
    let gatewayDisplayStatusText: String
    let nodeStatusText: String
    let operatorStatusText: String

    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            Text(verbatim: self.name)
                .font(OpenClawType.monoHeadline)
                .foregroundStyle(.primary)
            Text(verbatim: self.debugID)
                .font(OpenClawType.monoFootnote)
                .foregroundStyle(.secondary)

            VStack(alignment: .leading, spacing: 2) {
                // Use verbatim strings so Bonjour-provided values can't be interpreted as
                // localized format strings (which can crash with Objective-C exceptions).
                Text(verbatim: "Discovery: \(self.discoveryStatusText)")
                    .font(OpenClawType.monoFootnote)
                Text(verbatim: "Status: \(self.gatewayDisplayStatusText)")
                    .font(OpenClawType.monoFootnote)
                Text(verbatim: "Node: \(self.nodeStatusText)")
                    .font(OpenClawType.monoFootnote)
                Text(verbatim: "Operator: \(self.operatorStatusText)")
                    .font(OpenClawType.monoFootnote)
            }
            .font(OpenClawType.monoFootnote)
            .foregroundStyle(.secondary)
        }
        .frame(maxWidth: Self.readableMonospaceWidth, alignment: .leading)
        .padding(.vertical, 14)
        .padding(.horizontal, 16)
        .frame(maxWidth: .infinity, alignment: .leading)
        .textSelection(.enabled)
        .background(OpenClawBrand.obsidian)
        .clipShape(RoundedRectangle(cornerRadius: OpenClawRadius.lg))
    }
}
