import SwiftUI
import SwiftData

struct ContentView: View {
    var body: some View {
        SystemsView()
    }
}

struct SystemsView: View {
    @Environment(\.modelContext) private var modelContext
    @EnvironmentObject var unitSettings: UnitSystemSettings
    @Query(sort: \ElectricalSystem.timestamp, order: .reverse) private var systems: [ElectricalSystem]
    @Query(sort: \SavedLoad.timestamp, order: .reverse) private var allLoads: [SavedLoad]
    @State private var systemNavigationTarget: SystemNavigationTarget?
    @State private var showingComponentLibrary = false
    @State private var showingSettings = false

    private let systemColorOptions = [
        "blue", "green", "orange", "red", "purple", "yellow",
        "pink", "teal", "indigo", "mint", "cyan", "brown", "gray"
    ]
    private let defaultSystemIconName = "building.2"
    private let systemIconMappings: [(keywords: [String], icon: String)] = [
        (["rv", "van", "camper", "motorhome", "coach"], "bus"),
        (["truck", "trailer", "rig"], "truck.box"),
        (["boat", "marine", "yacht", "sail"], "sailboat"),
        (["plane", "air", "flight"], "airplane"),
        (["ferry", "ship"], "ferry"),
        (["house", "home", "cabin", "cottage", "lodge"], "house"),
        (["building", "office", "warehouse", "factory", "facility"], "building"),
        (["camp", "tent", "outdoor"], "tent"),
        (["solar", "sun"], "sun.max"),
        (["battery", "storage"], "battery.100"),
        (["server", "data", "network", "rack"], "server.rack"),
        (["computer", "electronics", "lab", "tech"], "cpu"),
        (["gear", "mechanic", "machine", "workshop"], "gear"),
        (["tool", "maintenance", "repair", "shop"], "wrench.adjustable"),
        (["hammer", "carpentry"], "hammer"),
        (["light", "lighting", "lamp"], "lightbulb"),
        (["bolt", "power", "electric"], "bolt"),
        (["plug"], "powerplug"),
        (["engine", "generator", "motor"], "engine.combustion"),
        (["fuel", "diesel", "gas"], "fuelpump"),
        (["water", "pump", "tank"], "drop"),
        (["heat", "heater", "furnace"], "flame"),
        (["cold", "freeze", "cool"], "snowflake"),
        (["climate", "hvac", "temperature"], "thermometer")
    ]

    private struct SystemNavigationTarget: Identifiable, Hashable {
        let id = UUID()
        let system: ElectricalSystem
        let presentSystemEditor: Bool
        let loadToOpenOnAppear: SavedLoad?
        
        static func == (lhs: SystemNavigationTarget, rhs: SystemNavigationTarget) -> Bool {
            lhs.id == rhs.id
        }
        
        func hash(into hasher: inout Hasher) {
            hasher.combine(id)
        }
    }

    var body: some View {
        NavigationStack {
            Group {
                if systems.isEmpty {
                    systemsEmptyState
                } else {
                    List {
                        ForEach(systems) { system in
                            NavigationLink(destination: LoadsView(system: system)) {
                                HStack(spacing: 12) {
                                    ZStack {
                                        RoundedRectangle(cornerRadius: 10)
                                            .fill(colorForName(system.colorName))
                                            .frame(width: 44, height: 44)
                                        
                                        Image(systemName: system.iconName)
                                            .font(.title3)
                                            .foregroundColor(.white)
                                    }
                        
                        VStack(alignment: .leading, spacing: 4) {
                            Text(system.name)
                                .fontWeight(.medium)
                                
                            if !system.location.isEmpty {
                                Text(system.location)
                                    .font(.caption)
                                    .foregroundColor(.secondary)
                            }

                            Text(componentSummary(for: system))
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }
                        
                        Spacer()
                    }
                    .padding(.vertical, 4)
                            }
                        }
                        .onDelete(perform: deleteSystems)
                    }
                }
            }
            .navigationTitle("Systems")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        showingSettings = true
                    } label: {
                        Image(systemName: "gearshape")
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    HStack {
                        Button(action: {
                            createNewSystem()
                        }) {
                            Image(systemName: "plus")
                        }
                        EditButton()
                    }
                }
            }
            .navigationDestination(item: $systemNavigationTarget) { target in
                LoadsView(
                    system: target.system,
                    presentSystemEditorOnAppear: target.presentSystemEditor,
                    loadToOpenOnAppear: target.loadToOpenOnAppear
                )
            }
        }
        .sheet(isPresented: $showingComponentLibrary) {
            ComponentLibraryView { item in
                addComponentFromLibrary(item)
            }
        }
        .sheet(isPresented: $showingSettings) {
            SettingsView()
                .environmentObject(unitSettings)
        }
    }
    
    private var systemsEmptyState: some View {
        SystemsOnboardingView { name in
            createOnboardingSystem(named: name)
        }
    }
    
    private func createNewSystem() {
        let system = makeSystem()
        navigateToSystem(system, presentSystemEditor: true, loadToOpen: nil)
    }

    private func createNewSystem(named name: String) {
        let system = makeSystem(preferredName: name)
        navigateToSystem(system, presentSystemEditor: true, loadToOpen: nil)
    }

    private func createOnboardingSystem(named name: String) {
        let system = makeSystem(
            preferredName: name,
            colorName: randomSystemColorName()
        )
        navigateToSystem(system, presentSystemEditor: false, loadToOpen: nil)
    }

    private func navigateToSystem(_ system: ElectricalSystem, presentSystemEditor: Bool, loadToOpen: SavedLoad?, animated: Bool = true) {
        let target = SystemNavigationTarget(
            system: system,
            presentSystemEditor: presentSystemEditor,
            loadToOpenOnAppear: loadToOpen
        )

        if animated {
            systemNavigationTarget = target
        } else {
            var transaction = Transaction()
            transaction.disablesAnimations = true
            withTransaction(transaction) {
                systemNavigationTarget = target
            }
        }
    }

    @discardableResult
    private func makeSystem(preferredName: String? = nil, colorName: String? = nil, iconName: String? = nil) -> ElectricalSystem {
        let existingNames = Set(systems.map { $0.name })
        let trimmedPreferred = preferredName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        let baseName = trimmedPreferred.isEmpty ? String(localized: "default.system.new", comment: "Default name for a newly created system") : trimmedPreferred
        var systemName = baseName
        var counter = 2

        while existingNames.contains(systemName) {
            systemName = "\(baseName) \(counter)"
            counter += 1
        }

        let resolvedColorName = colorName ?? "blue"
        let resolvedIconName = iconName ?? systemIconName(for: systemName)

        let newSystem = ElectricalSystem(
            name: systemName,
            location: "",
            iconName: resolvedIconName,
            colorName: resolvedColorName
        )
        modelContext.insert(newSystem)
        return newSystem
    }

    private func addComponentFromLibrary(_ item: ComponentLibraryItem) {
        let system = makeSystem()
        let load = createLoad(from: item, in: system)
        navigateToSystem(system, presentSystemEditor: false, loadToOpen: load, animated: false)
    }

    private func createLoad(from item: ComponentLibraryItem, in system: ElectricalSystem) -> SavedLoad {
        let baseName = item.name.isEmpty ? String(localized: "default.load.library", comment: "Default name when importing a library load") : item.name
        let loadName = uniqueLoadName(for: system, startingWith: baseName)
        let voltage = item.displayVoltage ?? 12.0

        let power: Double
        if let watt = item.watt {
            power = watt
        } else if let derivedCurrent = item.current, voltage > 0 {
            power = derivedCurrent * voltage
        } else {
            power = 0
        }

        let current: Double
        if let explicitCurrent = item.current {
            current = explicitCurrent
        } else if voltage > 0 {
            current = power / voltage
        } else {
            current = 0
        }

        let affiliateLink = item.primaryAffiliateLink

        let newLoad = SavedLoad(
            name: loadName,
            voltage: voltage,
            current: current,
            power: power,
            length: 10.0,
            crossSection: 1.0,
            iconName: "lightbulb",
            colorName: "blue",
            isWattMode: item.watt != nil,
            system: system,
            remoteIconURLString: item.iconURL?.absoluteString,
            affiliateURLString: affiliateLink?.url.absoluteString,
            affiliateCountryCode: affiliateLink?.country
        )

        modelContext.insert(newLoad)
        return newLoad
    }

    private func uniqueLoadName(for system: ElectricalSystem, startingWith baseName: String) -> String {
        let descriptor = FetchDescriptor<SavedLoad>()
        let fetchedLoads = (try? modelContext.fetch(descriptor)) ?? []
        let existingNames = Set(fetchedLoads.filter { $0.system == system }.map { $0.name })

        if !existingNames.contains(baseName) {
            return baseName
        }

        var counter = 2
        var candidate = "\(baseName) \(counter)"

        while existingNames.contains(candidate) {
            counter += 1
            candidate = "\(baseName) \(counter)"
        }

        return candidate
    }
    
    private func deleteSystems(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                let system = systems[index]
                deleteLoads(for: system)
                modelContext.delete(system)
            }
        }
    }

    private func deleteLoads(for system: ElectricalSystem) {
        let descriptor = FetchDescriptor<SavedLoad>()
        if let loads = try? modelContext.fetch(descriptor) {
            for load in loads where load.system == system {
                modelContext.delete(load)
            }
        }
    }

    private func loads(for system: ElectricalSystem) -> [SavedLoad] {
        allLoads.filter { $0.system == system }
    }

    private func componentSummary(for system: ElectricalSystem) -> String {
        let systemLoads = loads(for: system)
        guard !systemLoads.isEmpty else {
            return String(localized: "system.list.no.components", comment: "Message shown when a system has no components yet")
        }

        let count = systemLoads.count
        let totalPower = systemLoads.reduce(0.0) { $0 + $1.power }

        let formattedPower: String
        if totalPower >= 1000 {
            formattedPower = String(format: "%.1fkW", totalPower / 1000)
        } else {
            formattedPower = String(format: "%.0fW", totalPower)
        }

        let format = NSLocalizedString(
            "system.list.component.summary",
            comment: "Summary showing number of components and the total power"
        )
        return String.localizedStringWithFormat(format, count, formattedPower)
    }

    private func randomSystemColorName() -> String {
        systemColorOptions.randomElement() ?? "blue"
    }

    private func systemIconName(for name: String) -> String {
        let normalized = name
            .folding(options: [.diacriticInsensitive, .caseInsensitive], locale: .current)
            .lowercased()

        for mapping in systemIconMappings {
            if mapping.keywords.contains(where: { keyword in normalized.contains(keyword) }) {
                return mapping.icon
            }
        }

        return defaultSystemIconName
    }

    private func colorForName(_ colorName: String) -> Color {
        switch colorName {
        case "blue": return .blue
        case "green": return .green
        case "orange": return .orange
        case "red": return .red
        case "purple": return .purple
        case "yellow": return .yellow
        case "pink": return .pink
        case "teal": return .teal
        case "indigo": return .indigo
        case "mint": return .mint
        case "cyan": return .cyan
        case "brown": return .brown
        case "gray": return .gray
        default: return .blue
        }
    }
}

struct LoadsView: View {
    @Environment(\.modelContext) private var modelContext
    @EnvironmentObject var unitSettings: UnitSystemSettings
    @Query(sort: \SavedLoad.timestamp, order: .reverse) private var allLoads: [SavedLoad]
    @State private var newLoadToEdit: SavedLoad?
    @State private var showingSystemEditor = false
    @State private var hasPresentedSystemEditorOnAppear = false
    @State private var hasOpenedLoadOnAppear = false
    @State private var showingComponentLibrary = false
    @State private var showingSystemBOM = false
    
    let system: ElectricalSystem
    private let presentSystemEditorOnAppear: Bool
    private let loadToOpenOnAppear: SavedLoad?
    
    init(system: ElectricalSystem, presentSystemEditorOnAppear: Bool = false, loadToOpenOnAppear: SavedLoad? = nil) {
        self.system = system
        self.presentSystemEditorOnAppear = presentSystemEditorOnAppear
        self.loadToOpenOnAppear = loadToOpenOnAppear
    }
    
    private var savedLoads: [SavedLoad] {
        allLoads.filter { $0.system == system }
    }

    var body: some View {
        VStack(spacing: 0) {
            if savedLoads.isEmpty {
                emptyStateView
            } else {
                librarySection

                List {
                    ForEach(savedLoads) { load in
                        NavigationLink(destination: CalculatorView(savedLoad: load)) {
                            HStack(spacing: 12) {
                                LoadIconView(
                                    remoteIconURLString: load.remoteIconURLString,
                                    fallbackSystemName: load.iconName,
                                    fallbackColor: colorForName(load.colorName),
                                    size: 44)
                                
                                VStack(alignment: .leading, spacing: 6) {
                                    Text(load.name)
                                        .fontWeight(.medium)
                                        .lineLimit(1)
                                        .truncationMode(.tail)
                                    
                                    // Secondary info
                                    HStack {
                                        Group {
                                            Text(String(format: "%.1fV", load.voltage))
                                            Text("•")
                                            if load.isWattMode {
                                                Text(String(format: "%.0fW", load.power))
                                            } else {
                                                Text(String(format: "%.1fA", load.current))
                                            }
                                            Text("•")
                                            Text(String(format: "%.1f%@", 
                                                unitSettings.unitSystem == .metric ? load.length : load.length * 3.28084, 
                                                unitSettings.unitSystem.lengthUnit))
                                        }
                                        .font(.caption)
                                        .foregroundColor(.secondary)
                                        Spacer()
                                    }
                                    
                                    // Prominent fuse and wire gauge display
                                    HStack(spacing: 12) {
                                        HStack(spacing: 4) {
                                            Text("FUSE")
                                                .font(.caption2)
                                                .fontWeight(.medium)
                                                .foregroundColor(.secondary)
                                            Text("\(recommendedFuse(for: load))A")
                                                .font(.subheadline)
                                                .fontWeight(.bold)
                                                .foregroundColor(.orange)
                                        }
                                        .padding(.horizontal, 8)
                                        .padding(.vertical, 4)
                                        .background(Color.orange.opacity(0.1))
                                        .cornerRadius(6)
                                        
                                        HStack(spacing: 4) {
                                            Text("WIRE")
                                                .font(.caption2)
                                                .fontWeight(.medium)
                                                .foregroundColor(.secondary)
                                            Text(String(format: unitSettings.unitSystem == .imperial ? "%.0f AWG" : "%.1fmm²",
                                                unitSettings.unitSystem == .imperial ? awgFromCrossSection(load.crossSection) : load.crossSection))
                                                .font(.subheadline)
                                                .fontWeight(.bold)
                                                .foregroundColor(.blue)
                                        }
                                        .padding(.horizontal, 8)
                                        .padding(.vertical, 4)
                                        .background(Color.blue.opacity(0.1))
                                        .cornerRadius(6)
                                        
                                        Spacer()
                                    }
                                }
                            }
                            .padding(.vertical, 4)
                        }
                    }
                    .onDelete(perform: deleteLoads)
                }
            }
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .principal) {
                Button(action: {
                    showingSystemEditor = true
                }) {
                    HStack(spacing: 8) {
                        ZStack {
                            RoundedRectangle(cornerRadius: 6)
                                .fill(colorForName(system.colorName))
                                .frame(width: 24, height: 24)
                            
                            Image(systemName: system.iconName)
                                .font(.system(size: 12))
                                .foregroundColor(.white)
                        }
                        
                        Text(system.name)
                            .font(.headline)
                            .fontWeight(.semibold)
                            .foregroundColor(.primary)
                    }
                }
            }
            
            ToolbarItem(placement: .navigationBarTrailing) {
                HStack {
                    if !savedLoads.isEmpty {
                        Button(action: {
                            showingSystemBOM = true
                        }) {
                            Image(systemName: "list.bullet.rectangle")
                        }
                    }
                    Button(action: {
                        createNewLoad()
                    }) {
                        Image(systemName: "plus")
                    }
                    EditButton()
                }
            }
        }
        .navigationDestination(item: $newLoadToEdit) { load in
            CalculatorView(savedLoad: load)
        }
        .sheet(isPresented: $showingComponentLibrary) {
            ComponentLibraryView { item in
                addComponent(item)
            }
        }
        .sheet(isPresented: $showingSystemBOM) {
            SystemBillOfMaterialsView(
                systemName: system.name,
                loads: savedLoads,
                unitSystem: unitSettings.unitSystem
            )
        }
        .sheet(isPresented: $showingSystemEditor) {
            SystemEditorView(
                systemName: Binding(
                    get: { system.name },
                    set: { system.name = $0 }
                ),
                location: Binding(
                    get: { system.location },
                    set: { system.location = $0 }
                ),
                iconName: Binding(
                    get: { system.iconName },
                    set: { system.iconName = $0 }
                ),
                colorName: Binding(
                    get: { system.colorName },
                    set: { system.colorName = $0 }
                )
            )
        }
        .onAppear {
            if presentSystemEditorOnAppear && !hasPresentedSystemEditorOnAppear {
                hasPresentedSystemEditorOnAppear = true
                DispatchQueue.main.async {
                    showingSystemEditor = true
                }
            }

            if let loadToOpen = loadToOpenOnAppear, !hasOpenedLoadOnAppear {
                hasOpenedLoadOnAppear = true
                DispatchQueue.main.async {
                    newLoadToEdit = loadToOpen
                }
            }
        }
    }
    
    private var librarySection: some View {
        VStack(spacing: 0) {
            HStack {
                VStack(alignment: .leading, spacing: 4) {
                    Text("Component Library")
                        .font(.headline)
                        .fontWeight(.semibold)
                    Text("Browse electrical components from VoltPlan")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
                
                Spacer()
                
                Button(action: {
                    showingComponentLibrary = true
                }) {
                    HStack(spacing: 6) {
                        Text("Browse")
                            .font(.subheadline)
                            .fontWeight(.medium)
                        Image(systemName: "arrow.up.right")
                            .font(.caption)
                    }
                    .foregroundColor(.blue)
                }
                .buttonStyle(.plain)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 12)
            .background(Color(.systemGroupedBackground))
            
            Divider()
        }
    }
    
    private var emptyStateView: some View {
        ComponentsOnboardingView(
            onCreate: { createNewLoad() },
            onBrowse: { showingComponentLibrary = true }
        )
    }

    private func deleteLoads(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(savedLoads[index])
            }
        }
    }
    
    private func createNewLoad() {
        let defaultName = String(localized: "default.load.new", comment: "Default name when creating a new load from system view")
        let loadName = uniqueLoadName(startingWith: defaultName)
        let newLoad = SavedLoad(
            name: loadName,
            voltage: 12.0,
            current: 5.0,
            power: 60.0, // 12V * 5A = 60W
            length: 10.0,
            crossSection: 1.0,
            iconName: "lightbulb",
            colorName: "blue",
            isWattMode: false,
            system: system,
            remoteIconURLString: nil
        )
        modelContext.insert(newLoad)
        
        // Navigate to the new load
        newLoadToEdit = newLoad
    }

    private func addComponent(_ item: ComponentLibraryItem) {
        let baseName = item.name.isEmpty ? "Library Load" : item.name
        let loadName = uniqueLoadName(startingWith: baseName)
        let voltage = item.displayVoltage ?? 12.0
        let power = item.watt ?? (item.current != nil ? item.current! * voltage : 0)
        let current: Double
        if let explicitCurrent = item.current {
            current = explicitCurrent
        } else if voltage > 0 {
            current = power / voltage
        } else {
            current = 0
        }

        let affiliateLink = item.primaryAffiliateLink

        let newLoad = SavedLoad(
            name: loadName,
            voltage: voltage,
            current: current,
            power: power,
            length: 10.0,
            crossSection: 1.0,
            iconName: "lightbulb",
            colorName: "blue",
            isWattMode: item.watt != nil,
            system: system,
            remoteIconURLString: item.iconURL?.absoluteString,
            affiliateURLString: affiliateLink?.url.absoluteString,
            affiliateCountryCode: affiliateLink?.country
        )

        modelContext.insert(newLoad)
        newLoadToEdit = newLoad
    }

    private func uniqueLoadName(startingWith baseName: String) -> String {
        let existingNames = Set(savedLoads.map { $0.name })

        if !existingNames.contains(baseName) {
            return baseName
        }

        var counter = 2
        var candidate = "\(baseName) \(counter)"

        while existingNames.contains(candidate) {
            counter += 1
            candidate = "\(baseName) \(counter)"
        }

        return candidate
    }
    
    private func colorForName(_ colorName: String) -> Color {
        switch colorName {
        case "blue": return .blue
        case "green": return .green
        case "orange": return .orange
        case "red": return .red
        case "purple": return .purple
        case "yellow": return .yellow
        case "pink": return .pink
        case "teal": return .teal
        case "indigo": return .indigo
        case "mint": return .mint
        case "cyan": return .cyan
        case "brown": return .brown
        case "gray": return .gray
        default: return .blue
        }
    }
    
    private func awgFromCrossSection(_ crossSectionMM2: Double) -> Double {
        let awgSizes = [(20, 0.519), (18, 0.823), (16, 1.31), (14, 2.08), (12, 3.31), 
                       (10, 5.26), (8, 8.37), (6, 13.3), (4, 21.2), (2, 33.6), 
                       (1, 42.4), (0, 53.5), (00, 67.4), (000, 85.0), (0000, 107.0)]
        
        // Find the closest AWG size
        let closest = awgSizes.min { abs($0.1 - crossSectionMM2) < abs($1.1 - crossSectionMM2) }
        return Double(closest?.0 ?? 20)
    }
    
    private func recommendedFuse(for load: SavedLoad) -> Int {
        let targetFuse = load.current * 1.25 // 125% of load current for safety
        
        // Common fuse values in amperes
        let standardFuses = [1, 2, 3, 5, 7, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500, 600, 700, 800]
        
        // Find the smallest standard fuse that's >= target
        return standardFuses.first { $0 >= Int(targetFuse.rounded(.up)) } ?? standardFuses.last!
    }
}




struct SystemView: View {
    var body: some View {
        NavigationStack {
            VStack(spacing: 24) {
                Spacer()
                
                VStack(spacing: 16) {
                    Image(systemName: "square.grid.3x2")
                        .font(.system(size: 48))
                        .foregroundColor(.secondary)
                    
                    Text("System View")
                        .font(.title2)
                        .fontWeight(.semibold)
                    
                    Text("Coming soon - manage your electrical systems and panels here.")
                        .font(.body)
                        .foregroundColor(.secondary)
                        .multilineTextAlignment(.center)
                        .padding(.horizontal, 48)
                }
                
                Spacer()
                Spacer()
            }
            .navigationTitle("System")
        }
    }
}

struct SettingsView: View {
    @EnvironmentObject var unitSettings: UnitSystemSettings
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        NavigationStack {
            Form {
                Section("Units") {
                    Picker("Unit System", selection: $unitSettings.unitSystem) {
                        ForEach(UnitSystem.allCases, id: \.self) { system in
                            Text(system.displayName).tag(system)
                        }
                    }
                    .pickerStyle(.segmented)
                }
                
                Section {
                    HStack {
                        Text("Wire Cross-Section:")
                        Spacer()
                        Text(unitSettings.unitSystem.wireAreaUnit)
                            .foregroundColor(.secondary)
                    }
                    
                    HStack {
                        Text("Length:")
                        Spacer()
                        Text(unitSettings.unitSystem.lengthUnit)
                            .foregroundColor(.secondary)
                    }
                } header: {
                    Text("Current Units")
                } footer: {
                    Text("Changing the unit system will apply to all calculations in the app.")
                }
                
                Section {
                    VStack(alignment: .leading, spacing: 12) {
                        HStack(spacing: 8) {
                            Image(systemName: "exclamationmark.triangle.fill")
                                .foregroundColor(.orange)
                                .font(.system(size: 18))
                            Text("Safety Disclaimer")
                                .font(.headline)
                                .fontWeight(.semibold)
                        }
                        
                        VStack(alignment: .leading, spacing: 8) {
                            Text("This application provides electrical calculations for educational and estimation purposes only.")
                                .font(.body)
                            
                            Text("Important:")
                                .font(.subheadline)
                                .fontWeight(.semibold)
                            
                            VStack(alignment: .leading, spacing: 4) {
                                Text("• Always consult qualified electricians for actual installations")
                                Text("• Follow all local electrical codes and regulations")
                                Text("• Electrical work should only be performed by licensed professionals")
                                Text("• These calculations may not account for all environmental factors")
                                Text("• The app developers assume no liability for electrical installations")
                            }
                            .font(.caption)
                            .foregroundColor(.secondary)
                        }
                    }
                    .padding(.vertical, 8)
                }
            }
            .navigationTitle("Settings")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Close") {
                        dismiss()
                    }
                }
            }
        }
    }
}

private struct SystemBillOfMaterialsView: View {
    let systemName: String
    let loads: [SavedLoad]
    let unitSystem: UnitSystem

    @Environment(\.dismiss) private var dismiss
    @Environment(\.openURL) private var openURL
    @State private var completedItemIDs: Set<String>
    @State private var suppressRowTapForID: String?

    private struct Item: Identifiable {
        enum Destination {
            case affiliate(URL)
            case amazonSearch(String)
        }

        let id: String
        let logicalID: String
        let title: String
        let detail: String
        let iconSystemName: String
        let destination: Destination
        let isPrimaryComponent: Bool
    }

    init(systemName: String, loads: [SavedLoad], unitSystem: UnitSystem) {
        self.systemName = systemName
        self.loads = loads
        self.unitSystem = unitSystem
        let initialKeys = loads.flatMap { load in
            load.bomCompletedItemIDs.map { SystemBillOfMaterialsView.storageKey(for: load, itemID: $0) }
        }
        _completedItemIDs = State(initialValue: Set(initialKeys))
        _suppressRowTapForID = State(initialValue: nil)
    }

    var body: some View {
        NavigationStack {
            List {
                if sortedLoads.isEmpty {
                    Section("Components") {
                        Text("No loads saved in this system yet.")
                            .font(.footnote)
                            .foregroundColor(.secondary)
                    }
                } else {
                    ForEach(sortedLoads) { load in
                        Section(header: sectionHeader(for: load)) {
                            ForEach(items(for: load)) { item in
                                let isCompleted = completedItemIDs.contains(item.id)
                                let destinationURL = destinationURL(for: item.destination, load: load)

                                HStack(spacing: 12) {
                                    let accessibilityLabel: String = {
                                        if isCompleted {
                                            let format = NSLocalizedString(
                                                "bom.accessibility.mark.incomplete",
                                                comment: "Accessibility label instructing VoiceOver to mark an item incomplete"
                                            )
                                            return String.localizedStringWithFormat(format, item.title)
                                        } else {
                                            let format = NSLocalizedString(
                                                "bom.accessibility.mark.complete",
                                                comment: "Accessibility label instructing VoiceOver to mark an item complete"
                                            )
                                            return String.localizedStringWithFormat(format, item.title)
                                        }
                                    }()

                                    Image(systemName: isCompleted ? "checkmark.circle.fill" : "circle")
                                        .foregroundColor(isCompleted ? .accentColor : .secondary)
                                        .imageScale(.large)
                                        .onTapGesture {
                                            setCompletion(!isCompleted, for: load, item: item)
                                            suppressRowTapForID = item.id
                                        }
                                        .accessibilityLabel(accessibilityLabel)

                                    VStack(alignment: .leading, spacing: 4) {
                                        Text(item.title)
                                            .font(.headline)
                                            .foregroundStyle(isCompleted ? Color.primary.opacity(0.7) : Color.primary)
                                            .strikethrough(isCompleted, color: .accentColor.opacity(0.6))

                                        if item.isPrimaryComponent {
                                            Text(String(localized: "component.fallback.name", comment: "Tag label marking an item as the component itself"))
                                                .font(.caption2.weight(.medium))
                                                .foregroundColor(.accentColor)
                                                .padding(.horizontal, 6)
                                                .padding(.vertical, 2)
                                                .background(Color.accentColor.opacity(0.15), in: Capsule())
                                        }

                                        Text(item.detail)
                                            .font(.subheadline)
                                            .foregroundColor(.secondary)
                                    }

                                    Spacer(minLength: 8)

                                    if destinationURL != nil {
                                        Image(systemName: "arrow.up.right")
                                            .font(.footnote.weight(.semibold))
                                            .foregroundColor(.secondary)
                                    }
                                }
                                .padding(.vertical, 10)
                                .contentShape(Rectangle())
                                .listRowInsets(EdgeInsets(top: 6, leading: 20, bottom: 6, trailing: 16))
                                .listRowBackground(
                                    Color(.secondarySystemGroupedBackground)
                                )
                                .onTapGesture {
                                    if suppressRowTapForID == item.id {
                                        suppressRowTapForID = nil
                                        return
                                    }
                                    if let destinationURL {
                                        openURL(destinationURL)
                                    }
                                    setCompletion(true, for: load, item: item)
                                    suppressRowTapForID = nil
                                    suppressRowTapForID = nil
                                }
                            }
                        }
                    }
                }

                Section {
                    Text(footerMessage)
                        .font(.footnote)
                        .foregroundColor(.secondary)
                        .padding(.vertical, 4)
                }
            }
            .listStyle(.insetGrouped)
            .navigationTitle(
                String(
                    format: NSLocalizedString(
                        "bom.navigation.title.system",
                        comment: "Navigation title for the bill of materials view"
                    ),
                    locale: Locale.current,
                    systemName
                )
            )
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Close") {
                        dismiss()
                    }
                }
            }
            .onAppear {
                refreshCompletedItems()
                suppressRowTapForID = nil
            }
        }
    }

    private var sortedLoads: [SavedLoad] {
        loads.sorted { lhs, rhs in
            lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending
        }
    }

    private func sectionHeader(for load: SavedLoad) -> some View {
        VStack(alignment: .leading, spacing: 2) {
            let fallbackTitle = String(localized: "component.fallback.name", comment: "Fallback title for a component that lacks a name")
            Text(load.name.isEmpty ? fallbackTitle : load.name)
                .font(.headline)
            Text(dateFormatter.string(from: load.timestamp))
                .font(.caption)
                .foregroundColor(.secondary)
        }
    }

    private func items(for load: SavedLoad) -> [Item] {
        let lengthValue: Double
        if unitSystem == .imperial {
            lengthValue = load.length * 3.28084
        } else {
            lengthValue = load.length
        }
        let lengthLabel = String(format: "%.1f %@", lengthValue, unitSystem.lengthUnit)

        let crossSectionLabel: String
        let gaugeQuery: String
        let unknownSizeLabel = String(localized: "bom.size.unknown", comment: "Fallback label when the cable size is not yet determined")

        if unitSystem == .imperial {
            let awg = awgFromCrossSection(load.crossSection)
            if awg > 0 {
                crossSectionLabel = String(format: "AWG %.0f", awg)
                gaugeQuery = String(format: "AWG %.0f", awg)
            } else {
                crossSectionLabel = unknownSizeLabel
                gaugeQuery = "battery cable"
            }
        } else {
            if load.crossSection > 0 {
                crossSectionLabel = String(format: "%.1f mm²", load.crossSection)
                gaugeQuery = String(format: "%.1f mm2", load.crossSection)
            } else {
                crossSectionLabel = unknownSizeLabel
                gaugeQuery = "battery cable"
            }
        }

        let cableDetail = "\(lengthLabel) • \(crossSectionLabel)"

        let calculatedPower = load.power > 0 ? load.power : load.voltage * load.current
        let powerDetail = String(format: "%.0f W @ %.1f V", calculatedPower, load.voltage)

        let fuseRating = recommendedFuse(for: load)
        let fuseDetailFormat = NSLocalizedString(
            "bom.fuse.detail",
            comment: "Description for the fuse item in the BOM list"
        )
        let fuseDetail = String.localizedStringWithFormat(fuseDetailFormat, fuseRating)

        let cableShoesDetailFormat = NSLocalizedString(
            "bom.terminals.detail",
            comment: "Description for the cable terminals item in the BOM list"
        )
        let cableShoesDetail = String.localizedStringWithFormat(cableShoesDetailFormat, crossSectionLabel.lowercased())

        let affiliateURL = load.affiliateURLString.flatMap { URL(string: $0) }
        let deviceQuery = load.name.isEmpty
            ? String(format: "DC device %.0fW %.0fV", calculatedPower, load.voltage)
            : load.name

        let redCableQuery = "\(gaugeQuery) red battery cable"
        let blackCableQuery = "\(gaugeQuery) black battery cable"
        let fuseQuery = "inline fuse holder \(fuseRating)A"
        let terminalQuery = "\(gaugeQuery) cable shoes"

        let items: [Item] = [
            Item(
                id: Self.storageKey(for: load, itemID: "component"),
                logicalID: "component",
                title: load.name.isEmpty ? String(localized: "component.fallback.name", comment: "Fallback name for a component when no name is provided") : load.name,
                detail: powerDetail,
                iconSystemName: "bolt.fill",
                destination: affiliateURL.map { .affiliate($0) } ?? .amazonSearch(deviceQuery),
                isPrimaryComponent: true
            ),
            Item(
                id: Self.storageKey(for: load, itemID: "cable-red"),
                logicalID: "cable-red",
                title: String(localized: "bom.item.cable.red", comment: "Title for the red power cable item"),
                detail: cableDetail,
                iconSystemName: "bolt.horizontal.circle",
                destination: .amazonSearch(redCableQuery),
                isPrimaryComponent: false
            ),
            Item(
                id: Self.storageKey(for: load, itemID: "cable-black"),
                logicalID: "cable-black",
                title: String(localized: "bom.item.cable.black", comment: "Title for the black power cable item"),
                detail: cableDetail,
                iconSystemName: "bolt.horizontal.circle",
                destination: .amazonSearch(blackCableQuery),
                isPrimaryComponent: false
            ),
            Item(
                id: Self.storageKey(for: load, itemID: "fuse"),
                logicalID: "fuse",
                title: String(localized: "bom.item.fuse", comment: "Title for the fuse and holder item"),
                detail: fuseDetail,
                iconSystemName: "bolt.shield",
                destination: .amazonSearch(fuseQuery),
                isPrimaryComponent: false
            ),
            Item(
                id: Self.storageKey(for: load, itemID: "terminals"),
                logicalID: "terminals",
                title: String(localized: "bom.item.terminals", comment: "Title for the cable terminals item"),
                detail: cableShoesDetail,
                iconSystemName: "wrench.and.screwdriver",
                destination: .amazonSearch(terminalQuery),
                isPrimaryComponent: false
            )
        ]

        return items
    }

    private func destinationURL(for destination: Item.Destination, load: SavedLoad) -> URL? {
        switch destination {
        case .affiliate(let url):
            return url
        case .amazonSearch(let query):
            let countryCode = load.affiliateCountryCode ?? Locale.current.region?.identifier
            return AmazonAffiliate.searchURL(query: query, countryCode: countryCode)
        }
    }

    private static func storageKey(for load: SavedLoad, itemID: String) -> String {
        if load.identifier.isEmpty {
            load.identifier = UUID().uuidString
        }
        return "\(load.identifier)::\(itemID)"
    }

    private func setCompletion(_ isCompleted: Bool, for load: SavedLoad, item: Item) {
        if isCompleted {
            completedItemIDs.insert(item.id)
        } else {
            completedItemIDs.remove(item.id)
        }

        if load.identifier.isEmpty {
            load.identifier = UUID().uuidString
        }

        var stored = Set(load.bomCompletedItemIDs)
        if isCompleted {
            stored.insert(item.logicalID)
        } else {
            stored.remove(item.logicalID)
        }
        load.bomCompletedItemIDs = Array(stored).sorted()
    }

    private func refreshCompletedItems() {
        let keys = loads.flatMap { load in
            load.bomCompletedItemIDs.map { Self.storageKey(for: load, itemID: $0) }
        }
        completedItemIDs = Set(keys)
    }

    private func recommendedFuse(for load: SavedLoad) -> Int {
        let targetFuse = load.current * 1.25
        let standardFuses = [1, 2, 3, 5, 7, 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500, 600, 700, 800]
        return standardFuses.first { $0 >= Int(targetFuse.rounded(.up)) } ?? standardFuses.last ?? 0
    }

    private func awgFromCrossSection(_ crossSectionMM2: Double) -> Double {
        let mapping: [(awg: Double, area: Double)] = [
            (20, 0.519), (18, 0.823), (16, 1.31), (14, 2.08), (12, 3.31), (10, 5.26),
            (8, 8.37), (6, 13.3), (4, 21.2), (2, 33.6), (1, 42.4), (0, 53.5),
            (00, 67.4), (000, 85.0), (0000, 107.0)
        ]

        guard crossSectionMM2 > 0 else { return 0 }

        let closest = mapping.min { lhs, rhs in
            abs(lhs.area - crossSectionMM2) < abs(rhs.area - crossSectionMM2)
        }

        return closest?.awg ?? 0
    }

    private var footerMessage: String {
        NSLocalizedString(
            "affiliate.disclaimer",
            comment: "Footer note reminding users that affiliate purchases may support the app"
        )
    }

    private var dateFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        formatter.timeStyle = .short
        return formatter
    }
}


#Preview {
    ContentView()
        .modelContainer(for: Item.self, inMemory: true)
        .environmentObject(UnitSystemSettings())
}
