//
//  ChargedDeviceLibrarySheetView.swift
//  USB Meter
//
//  Created by Codex on 10/04/2026.
//

import SwiftUI
import UIKit

enum ChargedDeviceLibraryMode {
    case device
    case charger

    var kind: ChargedDeviceKind {
        switch self {
        case .device:
            return .device
        case .charger:
            return .charger
        }
    }

    var title: String {
        switch self {
        case .device:
            return "Devices"
        case .charger:
            return "Chargers"
        }
    }

    var singularTitle: String {
        switch self {
        case .device:
            return "Device"
        case .charger:
            return "Charger"
        }
    }
}

struct ChargedDeviceLibrarySheetView: View {
    @EnvironmentObject private var appData: AppData
    @Environment(\.dismiss) private var dismiss

    let meterMACAddress: String
    let meterTint: Color
    let mode: ChargedDeviceLibraryMode
    /// true = standalone sheet with own NavigationView; false = pushed into parent nav stack
    let standalone: Bool

    @State private var showingNewEditor = false
    @State private var editingChargedDevice: ChargedDeviceSummary?
    @State private var pendingDeletion: ChargedDeviceSummary?

    init(
        meterMACAddress: String,
        meterTint: Color,
        mode: ChargedDeviceLibraryMode,
        standalone: Bool = true
    ) {
        self.meterMACAddress = meterMACAddress
        self.meterTint = meterTint
        self.mode = mode
        self.standalone = standalone
    }

    var body: some View {
        if standalone {
            NavigationView { listContent }
                .navigationViewStyle(StackNavigationViewStyle())
        } else {
            listContent
        }
    }

    private var listContent: some View {
        List {
            if displayedChargedDevices.isEmpty {
                VStack(alignment: .leading, spacing: 10) {
                    HStack(spacing: 8) {
                        Text("No \(mode.title.lowercased()) yet.")
                            .font(.headline)
                        ContextInfoButton(
                            title: mode.title,
                            message: emptyStateDescription
                        )
                    }
                }
                .padding(.vertical, 10)
                .listRowBackground(Color.clear)
            } else {
                ForEach(displayedChargedDevices) { chargedDevice in
                    Button {
                        select(chargedDevice)
                        dismiss()
                    } label: {
                        ChargedDeviceLibraryRowView(
                            chargedDevice: chargedDevice,
                            isSelected: chargedDevice.id == selectedDeviceID
                        )
                    }
                    .buttonStyle(.plain)
                    .swipeActions(edge: .trailing, allowsFullSwipe: false) {
                        Button(role: .destructive) {
                            pendingDeletion = chargedDevice
                        } label: {
                            Label("Delete", systemImage: "trash")
                        }
                        Button {
                            editingChargedDevice = chargedDevice
                        } label: {
                            Label("Edit", systemImage: "pencil")
                        }
                        .tint(.blue)
                    }
                    .contextMenu {
                        Button {
                            editingChargedDevice = chargedDevice
                        } label: {
                            Label("Edit \(mode.singularTitle)", systemImage: "pencil")
                        }
                        Button(role: .destructive) {
                            pendingDeletion = chargedDevice
                        } label: {
                            Label("Delete \(mode.singularTitle)", systemImage: "trash")
                        }
                    }
                }
            }
        }
        .listStyle(InsetGroupedListStyle())
        .background(
            LinearGradient(
                colors: [meterTint.opacity(0.14), Color.clear],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
            .ignoresSafeArea()
        )
        .navigationTitle(mode.title)
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .cancellationAction) {
                if standalone {
                    Button("Done") { dismiss() }
                }
            }
            ToolbarItem(placement: .confirmationAction) {
                Button("New") { showingNewEditor = true }
            }
        }
        .sheet(isPresented: $showingNewEditor) {
            newEditorSheet
        }
        .sheet(item: $editingChargedDevice) { device in
            editEditorSheet(device)
        }
        .confirmationDialog(
            "Delete \(pendingDeletion?.name ?? mode.singularTitle)?",
            isPresented: Binding(
                get: { pendingDeletion != nil },
                set: { if !$0 { pendingDeletion = nil } }
            ),
            titleVisibility: .visible
        ) {
            Button("Delete", role: .destructive) {
                if let device = pendingDeletion {
                    _ = appData.deleteChargedDevice(id: device.id)
                    pendingDeletion = nil
                }
            }
            Button("Cancel", role: .cancel) { pendingDeletion = nil }
        } message: {
            Text("This will permanently remove the \(mode.singularTitle.lowercased()) and all associated data.")
        }
    }

    @ViewBuilder
    private var newEditorSheet: some View {
        if mode == .charger {
            ChargerEditorSheetView(
                appData: appData,
                meterMACAddress: meterMACAddress
            )
        } else {
            ChargedDeviceEditorSheetView(meterMACAddress: meterMACAddress)
                .environmentObject(appData)
        }
    }

    @ViewBuilder
    private func editEditorSheet(_ chargedDevice: ChargedDeviceSummary) -> some View {
        if chargedDevice.isCharger {
            ChargerEditorSheetView(
                appData: appData,
                chargedDevice: chargedDevice
            )
        } else {
            ChargedDeviceEditorSheetView(
                meterMACAddress: nil,
                chargedDevice: chargedDevice
            )
            .environmentObject(appData)
        }
    }

    private var displayedChargedDevices: [ChargedDeviceSummary] {
        switch mode {
        case .device:
            return appData.deviceSummaries
        case .charger:
            return appData.chargerSummaries
        }
    }

    private var selectedDeviceID: UUID? {
        switch mode {
        case .device:
            return appData.currentChargedDeviceSummary(for: meterMACAddress)?.id
        case .charger:
            return appData.currentChargerSummary(for: meterMACAddress)?.id
        }
    }

    private var emptyStateDescription: String {
        switch mode {
        case .device:
            return "Create one here, then select it before or during a charging session. The selected device becomes the default for this meter."
        case .charger:
            return "Create one here, then select it for wireless charging sessions. The selected charger becomes the default wireless source for this meter."
        }
    }

    private func select(_ chargedDevice: ChargedDeviceSummary) {
        switch mode {
        case .device:
            appData.assignChargedDevice(chargedDevice.id, to: meterMACAddress)
        case .charger:
            appData.assignCharger(chargedDevice.id, to: meterMACAddress)
        }
    }
}

private struct ChargedDeviceLibraryRowView: View {
    let chargedDevice: ChargedDeviceSummary
    let isSelected: Bool

    var body: some View {
        HStack(alignment: .top, spacing: 14) {
            ChargedDeviceQRCodeView(qrIdentifier: chargedDevice.qrIdentifier, side: 58)

            VStack(alignment: .leading, spacing: 6) {
                HStack {
                    ChargedDeviceIdentityLabelView(
                        chargedDevice: chargedDevice,
                        iconPointSize: 17
                    )
                    .font(.headline)
                    .foregroundColor(.primary)
                    Spacer()
                    if isSelected {
                        Image(systemName: "checkmark.circle.fill")
                            .foregroundColor(.green)
                    }
                }

                Text(chargedDevice.identityTitle)
                    .font(.caption.weight(.semibold))
                    .foregroundColor(.secondary)

                if chargedDevice.isCharger {
                    if !chargedDevice.chargerObservedVoltageSelections.isEmpty {
                        Text(
                            chargedDevice.chargerObservedVoltageSelections
                                .map { "\($0.format(decimalDigits: 1)) V" }
                                .joined(separator: ", ")
                        )
                        .font(.caption2)
                        .foregroundColor(.secondary)
                    } else if let chargerMaximumPowerWatts = chargedDevice.chargerMaximumPowerWatts {
                        Text("Max power: \(chargerMaximumPowerWatts.format(decimalDigits: 2)) W")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    } else {
                        Text("Wireless charger")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    }
                } else {
                    Text(chargedDevice.supportedChargingModes.map(\.title).joined(separator: " + "))
                        .font(.caption2)
                        .foregroundColor(.secondary)

                    if let capacity = chargedDevice.estimatedBatteryCapacityWh {
                        Text("Estimated capacity: \(capacity.format(decimalDigits: 2)) Wh")
                            .font(.caption)
                            .foregroundColor(.secondary)
                    }

                    if let minimumCurrent = chargedDevice.minimumCurrentAmps {
                        Text("Completion current: \(minimumCurrent.format(decimalDigits: 2)) A")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    }
                }
            }
        }
        .padding(.vertical, 4)
    }
}

struct ChargedDeviceIdentityLabelView: View {
    let chargedDevice: ChargedDeviceSummary
    var iconPointSize: CGFloat = 15

    var body: some View {
        HStack(alignment: .firstTextBaseline, spacing: 8) {
            ChargedDeviceTemplateIconView(
                icon: chargedDevice.identityIcon,
                fallbackSystemName: chargedDevice.fallbackIdentitySymbolName,
                pointSize: iconPointSize
            )
            Text(chargedDevice.name)
        }
    }
}

struct ChargedDeviceTemplateLabelView: View {
    let template: ChargedDeviceTemplateDefinition
    var iconPointSize: CGFloat = 15

    var body: some View {
        HStack(alignment: .firstTextBaseline, spacing: 8) {
            ChargedDeviceTemplateIconView(
                icon: template.icon,
                fallbackSystemName: template.deviceClass.symbolName,
                pointSize: iconPointSize
            )
            Text(template.name)
        }
    }
}

struct ChargedDeviceTemplateIconView: View {
    let icon: ChargedDeviceTemplateIcon
    let fallbackSystemName: String
    var pointSize: CGFloat = 15

    var body: some View {
        Group {
            if let assetName = resolvedAssetName {
                Image(assetName)
                    .renderingMode(.template)
                    .resizable()
                    .scaledToFit()
            } else {
                Image(systemName: resolvedSystemSymbolName)
                    .font(.system(size: pointSize))
            }
        }
        .frame(width: pointSize + 2, height: pointSize + 2)
    }

    private var resolvedAssetName: String? {
        guard icon.type == .asset, UIImage(named: icon.name) != nil else {
            return nil
        }
        return icon.name
    }

    private var resolvedSystemSymbolName: String {
        let candidate = icon.resolvedSystemSymbolName(fallbackSystemName: fallbackSystemName)
        if UIImage(systemName: candidate) != nil {
            return candidate
        }

        if let fallbackSystemName = icon.fallbackSystemName,
           UIImage(systemName: fallbackSystemName) != nil {
            return fallbackSystemName
        }

        return fallbackSystemName
    }
}

// MARK: - Sidebar Library View

/// Full-management library for the sidebar — navigates into ChargedDeviceDetailView
/// instead of select-and-dismiss like ChargedDeviceLibrarySheetView.
struct SidebarChargedDeviceLibraryView: View {
    @EnvironmentObject private var appData: AppData

    let mode: ChargedDeviceLibraryMode

    @State private var showingNewEditor = false
    @State private var editingChargedDevice: ChargedDeviceSummary?
    @State private var pendingDeletion: ChargedDeviceSummary?

    private var tint: Color {
        mode == .device ? .orange : .pink
    }

    var body: some View {
        List {
            if displayedDevices.isEmpty {
                VStack(alignment: .leading, spacing: 10) {
                    HStack(spacing: 8) {
                        Text("No \(mode.title.lowercased()) yet.")
                            .font(.headline)
                        ContextInfoButton(
                            title: mode.title,
                            message: emptyStateDescription
                        )
                    }
                }
                .padding(.vertical, 10)
                .listRowBackground(Color.clear)
            } else {
                ForEach(displayedDevices) { device in
                    NavigationLink(destination: ChargedDeviceDetailView(chargedDeviceID: device.id)) {
                        ChargedDeviceLibraryRowView(chargedDevice: device, isSelected: false)
                    }
                    .swipeActions(edge: .trailing, allowsFullSwipe: false) {
                        Button(role: .destructive) {
                            pendingDeletion = device
                        } label: {
                            Label("Delete", systemImage: "trash")
                        }
                        Button {
                            editingChargedDevice = device
                        } label: {
                            Label("Edit", systemImage: "pencil")
                        }
                        .tint(.blue)
                    }
                    .contextMenu {
                        Button {
                            editingChargedDevice = device
                        } label: {
                            Label("Edit \(mode.singularTitle)", systemImage: "pencil")
                        }
                        Button(role: .destructive) {
                            pendingDeletion = device
                        } label: {
                            Label("Delete \(mode.singularTitle)", systemImage: "trash")
                        }
                    }
                }
            }
        }
        .listStyle(InsetGroupedListStyle())
        .background(
            LinearGradient(
                colors: [tint.opacity(0.14), Color.clear],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
            .ignoresSafeArea()
        )
        .navigationTitle(mode.title)
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .primaryAction) {
                Button("New") { showingNewEditor = true }
            }
        }
        .sheet(isPresented: $showingNewEditor) { newEditorSheet }
        .sheet(item: $editingChargedDevice) { device in editEditorSheet(device) }
        .confirmationDialog(
            "Delete \(pendingDeletion?.name ?? mode.singularTitle)?",
            isPresented: Binding(
                get: { pendingDeletion != nil },
                set: { if !$0 { pendingDeletion = nil } }
            ),
            titleVisibility: .visible
        ) {
            Button("Delete", role: .destructive) {
                if let device = pendingDeletion {
                    _ = appData.deleteChargedDevice(id: device.id)
                    pendingDeletion = nil
                }
            }
            Button("Cancel", role: .cancel) { pendingDeletion = nil }
        } message: {
            Text("This will permanently remove the \(mode.singularTitle.lowercased()) and all associated data.")
        }
    }

    private var displayedDevices: [ChargedDeviceSummary] {
        mode == .device ? appData.deviceSummaries : appData.chargerSummaries
    }

    @ViewBuilder
    private var newEditorSheet: some View {
        if mode == .charger {
            ChargerEditorSheetView(appData: appData, meterMACAddress: nil)
        } else {
            ChargedDeviceEditorSheetView(meterMACAddress: nil)
                .environmentObject(appData)
        }
    }

    @ViewBuilder
    private func editEditorSheet(_ device: ChargedDeviceSummary) -> some View {
        if device.isCharger {
            ChargerEditorSheetView(appData: appData, chargedDevice: device)
        } else {
            ChargedDeviceEditorSheetView(meterMACAddress: nil, chargedDevice: device)
                .environmentObject(appData)
        }
    }

    private var emptyStateDescription: String {
        mode == .device
            ? "Create one here, then select it before or during a charging session. The selected device becomes the default for this meter."
            : "Create one here, then select it for wireless charging sessions. The selected charger becomes the default wireless source for this meter."
    }
}
