import SwiftUI

struct PreferencesView: View {
    private enum Tab: CaseIterable {
        case monitor, notifications, alerts, updates

        var title: String {
            switch self {
            case .monitor: return "Monitor"
            case .notifications: return "Notifications"
            case .alerts: return "Alerts"
            case .updates: return "Updates"
            }
        }

        var icon: String {
            switch self {
            case .monitor: return "waveform.path.ecg"
            case .notifications: return "bell.badge"
            case .alerts: return "exclamationmark.triangle"
            case .updates: return "square.and.arrow.down"
            }
        }
    }
    @EnvironmentObject private var sparkleUpdater: SparkleUpdater

    @AppStorage("pingInterval") private var storedPingInterval: Int = 10
    @AppStorage("refreshInterval") private var storedRefreshInterval: Int = 60
    @AppStorage("showIntervalIndicator") private var showIntervalIndicator: Bool = true

    @State private var pingIntervalSlider: Double = 10
    @State private var refreshIntervalSlider: Double = 60
    @State private var selection: Tab = .monitor
    @State private var hoveredTab: Tab?

    private let minimumInterval: Double = 10
    private let maximumPingInterval: Double = 60
    private let maximumRefreshInterval: Double = 600

    var body: some View {
        HStack(spacing: 0) {
            sidebar
            Divider()
            ScrollView {
                detailContent(for: selection)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .padding()
            }
            .frame(minWidth: 360, maxWidth: .infinity, maxHeight: .infinity)
        }
        .frame(minWidth: 560, minHeight: 360)
        .onAppear {
            pingIntervalSlider = Double(storedPingInterval)
            refreshIntervalSlider = Double(storedRefreshInterval)
        }
        .onChange(of: pingIntervalSlider) { _, newValue in
            storedPingInterval = Int(newValue)
        }
        .onChange(of: refreshIntervalSlider) { _, newValue in
            storedRefreshInterval = Int(newValue)
        }
    }

    private var sidebar: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Preferences")
                .font(.headline)
                .padding(.bottom, 8)

            ForEach(Tab.allCases, id: \.self) { tab in
                Button {
                    selection = tab
                } label: {
                    HStack(spacing: 10) {
                        Image(systemName: tab.icon)
                            .frame(width: 20)
                        Text(tab.title)
                        Spacer()
                    }
                    .padding(.vertical, 8)
                    .padding(.horizontal, 10)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .background(
                        Capsule(style: .continuous)
                            .fill(backgroundColor(for: tab))
                    )
                }
                .buttonStyle(.plain)
                .focusable(false)
                .contentShape(Capsule())
                .foregroundColor(selection == tab ? .white : .primary)
                .onHover { isHovering in
                    hoveredTab = isHovering ? tab : (hoveredTab == tab ? nil : hoveredTab)
                }
            }

            Spacer()
        }
        .padding()
        .frame(width: 180, alignment: .top)
    }

    @ViewBuilder
    private func detailContent(for tab: Tab) -> some View {
        VStack(alignment: .leading, spacing: 12) {
            Text(tab.title)
                .font(.title2)
                .padding(.bottom, 12)

            switch tab {
            case .monitor:
                MonitorPreferencesView(
                    pingIntervalSlider: $pingIntervalSlider,
                    refreshIntervalSlider: $refreshIntervalSlider,
                    showIntervalIndicator: $showIntervalIndicator,
                    minimumInterval: minimumInterval,
                    maximumPingInterval: maximumPingInterval,
                    maximumRefreshInterval: maximumRefreshInterval,
                    pingChanged: handlePingSliderEditing(_:),
                    refreshChanged: handleRefreshSliderEditing(_:)
                )
            case .notifications:
                NotificationsPreferencesView()
            case .alerts:
                AlertsPreferencesView()
            case .updates:
                UpdatesPreferencesView()
                    .environmentObject(sparkleUpdater)
            }
        }
    }

    private func handlePingSliderEditing(_ editing: Bool) {
        if !editing {
            storedPingInterval = Int(pingIntervalSlider)
        }
    }

    private func handleRefreshSliderEditing(_ editing: Bool) {
        if !editing {
            storedRefreshInterval = Int(refreshIntervalSlider)
        }
    }
    private func backgroundColor(for tab: Tab) -> Color {
        if selection == tab {
            return Color.accentColor
        }
        if hoveredTab == tab {
            return Color.accentColor.opacity(0.2)
        }
        return Color.accentColor.opacity(0.08)
    }
}

private struct MonitorPreferencesView: View {
    @Binding var pingIntervalSlider: Double
    @Binding var refreshIntervalSlider: Double
    @Binding var showIntervalIndicator: Bool

    let minimumInterval: Double
    let maximumPingInterval: Double
    let maximumRefreshInterval: Double
    let pingChanged: (Bool) -> Void
    let refreshChanged: (Bool) -> Void

    var body: some View {
        VStack(alignment: .leading, spacing: 24) {
            intervalSection(
                title: "Ping interval",
                value: $pingIntervalSlider,
                range: minimumInterval...maximumPingInterval,
                onEditingChanged: pingChanged
            )

            intervalSection(
                title: "Refresh interval",
                value: $refreshIntervalSlider,
                range: minimumInterval...maximumRefreshInterval,
                onEditingChanged: refreshChanged
            )

            Divider()

            Toggle("Show interval indicator", isOn: $showIntervalIndicator)
                .toggleStyle(.switch)

            Spacer()
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }

    private func intervalSection(
        title: String,
        value: Binding<Double>,
        range: ClosedRange<Double>,
        onEditingChanged: @escaping (Bool) -> Void
    ) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack {
                Text(title)
                    .font(.headline)
                Spacer()
                Text("\(Int(value.wrappedValue)) seconds")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }

            Slider(
                value: value,
                in: range,
                step: 5
            ) {
                Text(title)
            } minimumValueLabel: {
                Text("\(Int(range.lowerBound))s")
                    .font(.caption)
                    .foregroundColor(.secondary)
            } maximumValueLabel: {
                Text("\(Int(range.upperBound))s")
                    .font(.caption)
                    .foregroundColor(.secondary)
            } onEditingChanged: { editing in
                onEditingChanged(editing)
            }
        }
    }
}

private struct UpdatesPreferencesView: View {
    @EnvironmentObject var sparkleUpdater: SparkleUpdater

    private var automaticallyChecksBinding: Binding<Bool> {
        Binding(
            get: { sparkleUpdater.automaticallyChecksForUpdates },
            set: { sparkleUpdater.automaticallyChecksForUpdates = $0 }
        )
    }

    private var automaticallyDownloadsBinding: Binding<Bool> {
        Binding(
            get: { sparkleUpdater.automaticallyDownloadsUpdates },
            set: { sparkleUpdater.automaticallyDownloadsUpdates = $0 }
        )
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 18) {
            Toggle("Automatically check for updates", isOn: automaticallyChecksBinding)
            Toggle("Automatically download updates", isOn: automaticallyDownloadsBinding)

            Button(action: sparkleUpdater.checkForUpdates) {
                Label("Check for Updates Now", systemImage: "sparkles")
            }

            Text("Updates are delivered via Sparkle. Configure your appcast URL and public EdDSA key in Info.plist (keys `SUFeedURL` and `SUPublicEDKey`).")
                .font(.caption)
                .foregroundColor(.secondary)
                .padding(.top, 4)

            Spacer()
        }
        .toggleStyle(.switch)
        .frame(maxWidth: .infinity, alignment: .leading)
    }
}

private struct NotificationsPreferencesView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Notifications")
                .font(.headline)
                .padding(.bottom)

            Text("Configure notification behavior here.")
                .foregroundColor(.secondary)

            Spacer()
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding()
    }
}

private struct AlertsPreferencesView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Alerts")
                .font(.headline)
                .padding(.bottom)

            Text("Configure alert thresholds and behavior.")
                .foregroundColor(.secondary)

            Spacer()
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding()
    }
}

#Preview {
    PreferencesView()
}
