import SwiftUI

/// Post-Login Hub: zeigt User-Info + gebundene Geräte + Add-Device-Picker.
/// Limit erreicht → Add-Buttons disabled, User muss erst Release anfordern.
struct DeviceHubView: View {
    @Environment(WizardModel.self) private var model

    @State private var devices: [MagicDevice] = []
    @State private var profile: MagicUserProfile?
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var actionInFlight = false

    /// Hard-Limit muss synchron zum Backend (MAGIC_DEVICE_LIMIT) sein.
    private let deviceLimit = 5

    private var atLimit: Bool { devices.count >= deviceLimit }

    var body: some View {
        VStack(spacing: 0) {
            header
            Divider()
            content
        }
        .frame(minWidth: 720, minHeight: 540)
        .task {
            await loadProfile()
            await loadDevices()
        }
    }

    @ViewBuilder
    private var header: some View {
        HStack(spacing: 12) {
            avatarView

            VStack(alignment: .leading, spacing: 2) {
                Text(profile?.nickname ?? "ReBreak Magic")
                    .font(.title3.bold())
                HStack(spacing: 6) {
                    if let plan = profile?.plan {
                        Text(plan.capitalized)
                            .font(.caption2.bold())
                            .padding(.horizontal, 6)
                            .padding(.vertical, 2)
                            .background(Color.blue.opacity(0.12))
                            .foregroundStyle(.blue)
                            .clipShape(Capsule())
                    }
                    if let host = model.authSession?.label {
                        Text(host)
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                }
            }

            Spacer()

            Text("\(devices.count) / \(deviceLimit) Geräte")
                .font(.caption.monospacedDigit())
                .padding(.horizontal, 10)
                .padding(.vertical, 5)
                .background(atLimit ? Color.orange.opacity(0.15) : Color.blue.opacity(0.1))
                .foregroundStyle(atLimit ? Color.orange : Color.blue)
                .clipShape(Capsule())

            Button {
                Task { await model.handleLogout() }
            } label: {
                Image(systemName: "rectangle.portrait.and.arrow.right")
                    .help("Abmelden")
            }
            .buttonStyle(.borderless)
        }
        .padding(.horizontal, 24)
        .padding(.vertical, 16)
    }

    @ViewBuilder
    private var content: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 24) {
                addDeviceSection
                devicesSection
            }
            .padding(24)
        }
    }

    @ViewBuilder
    private var addDeviceSection: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                Text("Neues Gerät hinzufügen")
                    .font(.headline)
                Spacer()
                if atLimit {
                    Label("Limit erreicht — bitte unten ein Gerät freigeben", systemImage: "exclamationmark.triangle")
                        .font(.caption)
                        .foregroundStyle(.orange)
                }
            }

            HStack(spacing: 12) {
                addDeviceButton(
                    title: "iPhone / iPad",
                    subtitle: "Supervised + MDM + ReBreak-App",
                    icon: "iphone",
                    primary: true
                ) {
                    model.startIOSFlow()
                }

                addDeviceButton(
                    title: "Mac",
                    subtitle: "DNS-Filter-Profil installieren",
                    icon: "desktopcomputer",
                    primary: false
                ) {
                    model.startMacFlow()
                }
            }
            .disabled(atLimit)
            .opacity(atLimit ? 0.5 : 1.0)
        }
    }

    @ViewBuilder
    private func addDeviceButton(
        title: String,
        subtitle: String,
        icon: String,
        primary: Bool,
        action: @escaping () -> Void
    ) -> some View {
        Button(action: action) {
            HStack(spacing: 12) {
                Image(systemName: icon)
                    .font(.title2)
                    .frame(width: 32)
                VStack(alignment: .leading, spacing: 2) {
                    Text(title)
                        .font(.headline)
                    Text(subtitle)
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
                Spacer()
                Image(systemName: "chevron.right")
                    .font(.caption)
                    .foregroundStyle(.tertiary)
            }
            .padding(14)
            .frame(maxWidth: .infinity)
            .background(
                RoundedRectangle(cornerRadius: 10)
                    .fill(primary ? Color.blue.opacity(0.08) : Color(nsColor: .controlBackgroundColor))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 10)
                    .strokeBorder(primary ? Color.blue.opacity(0.3) : Color.gray.opacity(0.2), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
    }

    @ViewBuilder
    private var devicesSection: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                Text("Registrierte Geräte")
                    .font(.headline)
                Spacer()
                Button {
                    Task { await loadDevices() }
                } label: {
                    Image(systemName: "arrow.clockwise")
                }
                .buttonStyle(.borderless)
                .help("Aktualisieren")
                .disabled(isLoading)
            }

            if let error = errorMessage {
                Label(error, systemImage: "exclamationmark.triangle")
                    .font(.caption)
                    .foregroundStyle(.red)
                    .padding()
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .background(Color.red.opacity(0.08))
                    .clipShape(RoundedRectangle(cornerRadius: 8))
            }

            if isLoading && devices.isEmpty {
                HStack {
                    ProgressView().controlSize(.small)
                    Text("Lade Geräte…").font(.caption).foregroundStyle(.secondary)
                }
                .frame(maxWidth: .infinity, minHeight: 120)
            } else if devices.isEmpty {
                emptyState
            } else {
                VStack(spacing: 8) {
                    ForEach(devices) { device in
                        HubDeviceRow(device: device) { action in
                            await handleAction(action, device: device)
                        }
                    }
                }
            }
        }
    }

    @ViewBuilder
    private var emptyState: some View {
        VStack(spacing: 10) {
            Image(systemName: "checkmark.shield")
                .font(.system(size: 42))
                .foregroundStyle(.secondary)
            Text("Noch keine Geräte registriert")
                .font(.callout.bold())
            Text("Wähle oben „iPhone / iPad“ oder „Mac“ um anzufangen.")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .frame(maxWidth: .infinity, minHeight: 160)
        .padding()
        .background(Color(nsColor: .controlBackgroundColor).opacity(0.5))
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }

    private func loadDevices() async {
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }
        do {
            devices = try await MagicAPIClient.shared.listDevices()
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    private func loadProfile() async {
        do {
            profile = try await MagicAPIClient.shared.fetchMe()
        } catch {
            // Profil-Fehler ist nicht-blockierend \u2014 nur Header f\u00e4llt auf Default zur\u00fcck
            profile = nil
        }
    }

    @ViewBuilder
    private var avatarView: some View {
        if let urlString = profile?.avatar, let url = URL(string: urlString) {
            AsyncImage(url: url) { phase in
                switch phase {
                case .success(let image):
                    image.resizable().scaledToFill()
                default:
                    avatarFallback
                }
            }
            .frame(width: 40, height: 40)
            .clipShape(Circle())
            .overlay(Circle().strokeBorder(Color.blue.opacity(0.2), lineWidth: 1))
        } else {
            avatarFallback
        }
    }

    @ViewBuilder
    private var avatarFallback: some View {
        ZStack {
            Circle().fill(Color.blue.opacity(0.15))
            if let initial = (profile?.nickname?.first).map(String.init) {
                Text(initial.uppercased())
                    .font(.headline)
                    .foregroundStyle(.blue)
            } else {
                Image(systemName: "shield.lefthalf.filled")
                    .foregroundStyle(.blue)
            }
        }
        .frame(width: 40, height: 40)
    }

    private func handleAction(_ action: HubDeviceAction, device: MagicDevice) async {
        guard !actionInFlight else { return }
        actionInFlight = true
        defer { actionInFlight = false }

        do {
            switch action {
            case .requestRelease:
                _ = try await MagicAPIClient.shared.requestRelease(deviceId: device.deviceId)
            case .cancelRelease:
                try await MagicAPIClient.shared.cancelRelease(deviceId: device.deviceId)
            }
            await loadDevices()
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}

// MARK: - Row

private enum HubDeviceAction {
    case requestRelease
    case cancelRelease
}

private struct HubDeviceRow: View {
    let device: MagicDevice
    let onAction: (HubDeviceAction) async -> Void

    @State private var timeRemaining: String = ""
    @State private var timer: Timer?
    @State private var confirmingRelease = false

    private var platformIcon: String {
        let m = (device.model ?? "").lowercased()
        let h = device.hostname.lowercased()
        if m.contains("iphone") || h.contains("iphone") { return "iphone" }
        if m.contains("ipad") || h.contains("ipad") { return "ipad" }
        if m.contains("mac") || h.contains("mac") || h.contains("book") { return "desktopcomputer" }
        return "shield"
    }

    var body: some View {
        HStack(spacing: 14) {
            Image(systemName: platformIcon)
                .font(.title2)
                .foregroundStyle(.blue)
                .frame(width: 28)

            VStack(alignment: .leading, spacing: 2) {
                HStack(spacing: 6) {
                    Text(device.hostname)
                        .font(.callout.bold())
                    if device.resolvedSource == .protected || device.resolvedSource == .locked {
                        Text("Native-App")
                            .font(.caption2.bold())
                            .padding(.horizontal, 6)
                            .padding(.vertical, 2)
                            .background(Color.gray.opacity(0.15))
                            .foregroundStyle(.secondary)
                            .clipShape(Capsule())
                    }
                }
                HStack(spacing: 8) {
                    if let model = device.model {
                        Text(model).font(.caption2).foregroundStyle(.secondary)
                    }
                    if let os = device.osVersion {
                        Text("·").font(.caption2).foregroundStyle(.tertiary)
                        Text(os).font(.caption2).foregroundStyle(.secondary)
                    }
                }
            }

            Spacer()

            if device.resolvedSource == .protected || device.resolvedSource == .locked {
                Text("Verwaltung in der ReBreak-App")
                    .font(.caption2)
                    .foregroundStyle(.tertiary)
            } else if device.isReleasing {
                VStack(alignment: .trailing, spacing: 2) {
                    Label("Freigabe läuft", systemImage: "hourglass")
                        .font(.caption2.bold())
                        .foregroundStyle(.orange)
                    if !timeRemaining.isEmpty {
                        Text(timeRemaining).font(.caption2.monospacedDigit()).foregroundStyle(.secondary)
                    }
                }

                Button("Abbrechen") {
                    Task { await onAction(.cancelRelease) }
                }
                .buttonStyle(.borderless)
                .font(.caption)
            } else {
                Button(role: .destructive) {
                    confirmingRelease = true
                } label: {
                    Image(systemName: "trash")
                }
                .buttonStyle(.borderless)
                .help("Gerät freigeben")
                .confirmationDialog(
                    "Gerät freigeben?",
                    isPresented: $confirmingRelease,
                    titleVisibility: .visible
                ) {
                    Button("Freigabe anfordern", role: .destructive) {
                        Task { await onAction(.requestRelease) }
                    }
                    Button("Abbrechen", role: .cancel) { }
                } message: {
                    Text("Auf „\(device.hostname)“ muss die Freigabe bestätigt werden. Anschließend startet ein 24h-Cooldown bevor der Slot frei wird.")
                }
            }
        }
        .padding(.horizontal, 14)
        .padding(.vertical, 10)
        .background(Color(nsColor: .controlBackgroundColor))
        .clipShape(RoundedRectangle(cornerRadius: 8))
        .onAppear {
            updateTimeRemaining()
            timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
                updateTimeRemaining()
            }
        }
        .onDisappear { timer?.invalidate() }
    }

    private func updateTimeRemaining() {
        guard let releaseDate = device.releaseDate else {
            timeRemaining = ""
            return
        }
        let remaining = releaseDate.timeIntervalSince(Date())
        if remaining <= 0 {
            timeRemaining = "läuft ab…"
            return
        }
        let hours = Int(remaining) / 3600
        let mins = (Int(remaining) % 3600) / 60
        let secs = Int(remaining) % 60
        if hours > 0 {
            timeRemaining = String(format: "%dh %02dm", hours, mins)
        } else {
            timeRemaining = String(format: "%02d:%02d", mins, secs)
        }
    }
}

#Preview {
    DeviceHubView()
        .environment(WizardModel())
}
