//
//  LoadsView.swift
//  Cable
//
//  Created by Stefan Lange-Hegermann on 09.10.25.
//


import SwiftUI
import SwiftData

struct LoadsView: View {
    @Environment(\.modelContext) private var modelContext
    @EnvironmentObject var unitSettings: UnitSystemSettings
    @Query(sort: \SavedLoad.timestamp, order: .reverse) private var allLoads: [SavedLoad]
    @Query(sort: \SavedBattery.timestamp, order: .reverse) private var allBatteries: [SavedBattery]
    @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
    @State private var selectedComponentTab: ComponentTab = .components
    @State private var batteryDraft: BatteryConfiguration?
    @State private var activeStatus: LoadStatus?
    @State private var editMode: EditMode = .inactive
    
    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 }
    }
    
    private var savedBatteries: [SavedBattery] {
        allBatteries.filter { $0.system == system }
    }

    var body: some View {
        VStack(spacing: 0) {
            if savedLoads.isEmpty {
                emptyStateView
            } else {
                TabView(selection: $selectedComponentTab) {
                    componentsTab
                        .tag(ComponentTab.components)
                        .tabItem {
                            Label(
                                String(
                                    localized: "tab.components",
                                    bundle: .main,
                                    comment: "Tab title for components list"
                                ),
                                systemImage: "square.stack.3d.up"
                            )
                        }
                    BatteriesView(
                        system: system,
                        batteries: savedBatteries,
                        onEdit: { editBattery($0) },
                        onDelete: deleteBatteries
                    )
                        .tag(ComponentTab.batteries)
                        .tabItem {
                            Label(
                                String(
                                    localized: "tab.batteries",
                                    bundle: .main,
                                    comment: "Tab title for battery configurations"
                                ),
                                systemImage: "battery.100"
                            )
                        }
                    ChargersView(system: system)
                        .tag(ComponentTab.chargers)
                        .tabItem {
                            Label(
                                String(
                                    localized: "tab.chargers",
                                    bundle: .main,
                                    comment: "Tab title for chargers view"
                                ),
                                systemImage: "bolt.fill"
                            )
                        }
                }
                .environment(\.editMode, $editMode)
            }
        }
        .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 selectedComponentTab == .components {
                        Button(action: {
                            showingComponentLibrary = true
                        }) {
                            Image(systemName: "books.vertical")
                        }
                        .accessibilityIdentifier("component-library-button")
                    }
                    if !savedLoads.isEmpty && selectedComponentTab == .components {
                        Button(action: {
                            showingSystemBOM = true
                        }) {
                            Image(systemName: "list.bullet.rectangle")
                        }
                        .accessibilityIdentifier("system-bom-button")
                    }
                    Button(action: {
                        handlePrimaryAction()
                    }) {
                        Image(systemName: "plus")
                    }
                    .disabled(selectedComponentTab == .chargers)
                    if selectedComponentTab == .components {
                        EditButton()
                            .environment(\.editMode, $editMode)
                            .disabled(savedLoads.isEmpty)
                    } else if selectedComponentTab == .batteries {
                        EditButton()
                            .environment(\.editMode, $editMode)
                            .disabled(savedBatteries.isEmpty)
                    }
                }
            }
        }
        .navigationDestination(item: $newLoadToEdit) { load in
            CalculatorView(savedLoad: load)
        }
        .sheet(item: $batteryDraft) { draft in
            NavigationStack {
                BatteryEditorView(
                    configuration: draft,
                    onSave: { configuration in
                        saveBattery(configuration)
                        batteryDraft = nil
                    },
                    onCancel: {
                        batteryDraft = nil
                    }
                )
            }
        }
        .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 }
                )
            )
        }
        .alert(item: $activeStatus) { status in
            let detail = detailInfo(for: status)
            return Alert(
                title: Text(detail.title),
                message: Text(detail.message),
                dismissButton: .default(
                    Text(
                        NSLocalizedString(
                            "battery.bank.status.dismiss",
                            bundle: .main,
                            value: "Got it",
                            comment: "Dismiss button title for load status alert"
                        )
                    )
                )
            )
        }
        .onAppear {
            if presentSystemEditorOnAppear && !hasPresentedSystemEditorOnAppear {
                hasPresentedSystemEditorOnAppear = true
                DispatchQueue.main.async {
                    showingSystemEditor = true
                }
            }

            if let loadToOpen = loadToOpenOnAppear, !hasOpenedLoadOnAppear {
                hasOpenedLoadOnAppear = true
                DispatchQueue.main.async {
                    newLoadToEdit = loadToOpen
                }
            }
        }
        .onChange(of: selectedComponentTab) { newValue in
            if newValue == .chargers {
                editMode = .inactive
            }
        }
    }
    
    private var summarySection: some View {
        VStack(spacing: 0) {
            VStack(alignment: .leading, spacing: 10) {
                HStack(alignment: .firstTextBaseline) {
                    Text(loadsSummaryTitle)
                        .font(.headline.weight(.semibold))
                    Spacer()
                }

                ViewThatFits(in: .horizontal) {
                    HStack(spacing: 16) {
                        summaryMetric(
                            icon: "square.stack.3d.up",
                            label: loadsCountLabel,
                            value: "\(savedLoads.count)",
                            tint: .blue
                        )
                        summaryMetric(
                            icon: "bolt.fill",
                            label: loadsCurrentLabel,
                            value: formattedCurrent(totalCurrent),
                            tint: .orange
                        )
                        summaryMetric(
                            icon: "gauge.medium",
                            label: loadsPowerLabel,
                            value: formattedPower(totalPower),
                            tint: .green
                        )
                    }

                    VStack(alignment: .leading, spacing: 12) {
                        summaryMetric(
                            icon: "square.stack.3d.up",
                            label: loadsCountLabel,
                            value: "\(savedLoads.count)",
                            tint: .blue
                        )
                        summaryMetric(
                            icon: "bolt.fill",
                            label: loadsCurrentLabel,
                            value: formattedCurrent(totalCurrent),
                            tint: .orange
                        )
                        summaryMetric(
                            icon: "gauge.medium",
                            label: loadsPowerLabel,
                            value: formattedPower(totalPower),
                            tint: .green
                        )
                    }
                }

                if let status = loadStatus {
                    Button {
                        activeStatus = status
                    } label: {
                        statusBanner(for: status)
                    }
                    .buttonStyle(.plain)
                }
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 10)
            .background(Color(.systemGroupedBackground))

            Divider()
                .background(Color(.separator))
        }
    }

    private var componentsTab: some View {
        VStack(spacing: 0) {
            summarySection

            List {
                ForEach(savedLoads) { load in
                    Button {
                        selectLoad(load)
                    } label: {
                        loadRow(for: load)
                    }
                    .buttonStyle(.plain)
                    .listRowInsets(.init(top: 12, leading: 16, bottom: 12, trailing: 16))
                    .listRowSeparator(.hidden)
                    .listRowBackground(Color.clear)
                }
                .onDelete(perform: deleteLoads)
            }
            .listStyle(.plain)
            .scrollContentBackground(.hidden)
            .accessibilityIdentifier("loads-list")
        }
        .background(Color(.systemGroupedBackground))
    }

    private func selectLoad(_ load: SavedLoad) {
        newLoadToEdit = load
    }

    private func loadRow(for load: SavedLoad) -> some View {
        VStack(alignment: .leading, spacing: 14) {
            HStack(spacing: 12) {
                LoadIconView(
                    remoteIconURLString: load.remoteIconURLString,
                    fallbackSystemName: load.iconName,
                    fallbackColor: colorForName(load.colorName),
                    size: 48
                )

                VStack(alignment: .leading, spacing: 4) {
                    Text(load.name)
                        .font(.body.weight(.medium))
                        .lineLimit(1)
                        .truncationMode(.tail)

                    Text(loadSummary(for: load))
                        .font(.caption.weight(.medium))
                        .foregroundStyle(.secondary)
                        .padding(.horizontal, 8)
                        .padding(.vertical, 4)
                        .background(
                            Capsule(style: .continuous)
                                .fill(Color(.tertiarySystemBackground))
                        )
                }
                Spacer()
                Image(systemName: "chevron.right")
                    .font(.system(size: 14, weight: .semibold))
                    .foregroundStyle(.secondary)
            }

            ViewThatFits(in: .horizontal) {
                HStack(spacing: 12) {
                    metricBadge(
                        label: fuseMetricLabel,
                        value: "\(recommendedFuse(for: load)) A",
                        tint: .pink
                    )
                    metricBadge(
                        label: cableMetricLabel,
                        value: wireGaugeString(for: load),
                        tint: .teal
                    )
                    metricBadge(
                        label: lengthMetricLabel,
                        value: lengthString(for: load),
                        tint: .orange
                    )
                    Spacer()
                }

                VStack(alignment: .leading, spacing: 8) {
                    metricBadge(
                        label: fuseMetricLabel,
                        value: "\(recommendedFuse(for: load)) A",
                        tint: .pink
                    )
                    metricBadge(
                        label: cableMetricLabel,
                        value: wireGaugeString(for: load),
                        tint: .teal
                    )
                    metricBadge(
                        label: lengthMetricLabel,
                        value: lengthString(for: load),
                        tint: .orange
                    )
                }
            }
        }
        .padding(.vertical, 16)
        .padding(.horizontal, 16)
        .background(
            RoundedRectangle(cornerRadius: 18, style: .continuous)
                .fill(Color(.systemBackground))
        )
    }

    private func loadSummary(for load: SavedLoad) -> String {
        let voltageText = String(format: "%.1fV", load.voltage)
        let lengthText: String
        if unitSettings.unitSystem == .metric {
            lengthText = String(format: "%.1f%@", load.length, unitSettings.unitSystem.lengthUnit)
        } else {
            let imperialLength = load.length * 3.28084
            lengthText = String(format: "%.1f%@", imperialLength, unitSettings.unitSystem.lengthUnit)
        }
        let powerOrCurrent = load.isWattMode
            ? String(format: "%.0fW", load.power)
            : String(format: "%.1fA", load.current)
        return [voltageText, powerOrCurrent, lengthText].joined(separator: " • ")
    }

    private func wireGaugeString(for load: SavedLoad) -> String {
        if unitSettings.unitSystem == .imperial {
            let awgValue = awgFromCrossSection(load.crossSection)
            return String(format: "%.0f AWG", awgValue)
        } else {
            return String(format: "%.1f mm²", load.crossSection)
        }
    }

    private func lengthString(for load: SavedLoad) -> String {
        if unitSettings.unitSystem == .imperial {
            let imperialLength = load.length * 3.28084
            return String(format: "%.1f ft", imperialLength)
        } else {
            return String(format: "%.1f m", load.length)
        }
    }

    private var fuseMetricLabel: String {
        NSLocalizedString(
            "loads.metric.fuse",
            bundle: .main,
            value: "Fuse",
            comment: "Label for fuse metric in load detail row"
        )
    }

    private var cableMetricLabel: String {
        NSLocalizedString(
            "loads.metric.cable",
            bundle: .main,
            value: "Cable",
            comment: "Label for cable metric in load detail row"
        )
    }

    private var lengthMetricLabel: String {
        NSLocalizedString(
            "loads.metric.length",
            bundle: .main,
            value: "Length",
            comment: "Label for cable length metric in load detail row"
        )
    }

    private var loadsSummaryTitle: String {
        NSLocalizedString(
            "loads.overview.header.title",
            bundle: .main,
            value: "Load Overview",
            comment: "Title for the loads overview summary section"
        )
    }

    private var loadsCountLabel: String {
        NSLocalizedString(
            "loads.overview.metric.count",
            bundle: .main,
            value: "Loads",
            comment: "Label for number of loads metric"
        )
    }

    private var loadsCurrentLabel: String {
        NSLocalizedString(
            "loads.overview.metric.current",
            bundle: .main,
            value: "Total Current",
            comment: "Label for total load current metric"
        )
    }

    private var loadsPowerLabel: String {
        NSLocalizedString(
            "loads.overview.metric.power",
            bundle: .main,
            value: "Total Power",
            comment: "Label for total load power metric"
        )
    }

    private var totalCurrent: Double {
        savedLoads.reduce(0) { result, load in
            result + max(load.current, 0)
        }
    }

    private var totalPower: Double {
        savedLoads.reduce(0) { result, load in
            result + max(load.power, 0)
        }
    }

    private var loadStatus: LoadStatus? {
        guard !savedLoads.isEmpty else { return nil }
        let incompleteLoads = savedLoads.filter { load in
            load.length <= 0 || load.crossSection <= 0
        }
        if !incompleteLoads.isEmpty {
            return .missingDetails(count: incompleteLoads.count)
        }
        return nil
    }

    private func summaryMetric(icon: String, label: String, value: String, tint: Color) -> some View {
        VStack(alignment: .leading, spacing: 2) {
            HStack(spacing: 6) {
                Image(systemName: icon)
                    .font(.system(size: 14, weight: .semibold))
                    .foregroundStyle(tint)
                Text(value)
                    .font(.body.weight(.semibold))
            }
            Text(label.uppercased())
                .font(.caption2)
                .fontWeight(.medium)
                .foregroundStyle(.secondary)
        }
    }

    private func statusBanner(for status: LoadStatus) -> some View {
        HStack(spacing: 10) {
            Image(systemName: status.symbol)
                .font(.system(size: 16, weight: .semibold))
                .foregroundStyle(status.tint)
            Text(status.bannerText)
                .font(.subheadline.weight(.semibold))
                .foregroundStyle(status.tint)
            Spacer()
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 10)
        .background(
            RoundedRectangle(cornerRadius: 14, style: .continuous)
                .fill(status.tint.opacity(0.12))
        )
    }

    private func formattedCurrent(_ value: Double) -> String {
        let numberString = LoadsView.numberFormatter.string(from: NSNumber(value: value)) ?? String(format: "%.1f", value)
        return "\(numberString) A"
    }

    private func formattedPower(_ value: Double) -> String {
        let numberString = LoadsView.numberFormatter.string(from: NSNumber(value: value)) ?? String(format: "%.1f", value)
        return "\(numberString) W"
    }

    private func detailInfo(for status: LoadStatus) -> LoadStatusDetail {
        switch status {
        case .missingDetails(let count):
            let title = NSLocalizedString(
                "loads.overview.status.missing_details.title",
                bundle: .main,
                value: "Missing load details",
                comment: "Alert title when loads are missing required details"
            )
            let format = NSLocalizedString(
                "loads.overview.status.missing_details.message",
                bundle: .main,
                value: "Enter cable length and wire size for %d %@ to see accurate recommendations.",
                comment: "Alert message when loads are missing required details"
            )
            let loadWord = count == 1
                ? NSLocalizedString(
                    "loads.overview.status.missing_details.singular",
                    bundle: .main,
                    value: "load",
                    comment: "Singular noun for load"
                )
                : NSLocalizedString(
                    "loads.overview.status.missing_details.plural",
                    bundle: .main,
                    value: "loads",
                    comment: "Plural noun for loads"
                )
            let message = String(format: format, count, loadWord)
            return LoadStatusDetail(title: title, message: message)
        }
    }

    private static let numberFormatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.locale = .current
        formatter.minimumFractionDigits = 0
        formatter.maximumFractionDigits = 1
        return formatter
    }()

    private enum LoadStatus: Identifiable {
        case missingDetails(count: Int)

        var id: String {
            switch self {
            case .missingDetails(let count):
                return "missing-details-\(count)"
            }
        }

        var symbol: String {
            switch self {
            case .missingDetails:
                return "exclamationmark.triangle.fill"
            }
        }

        var tint: Color {
            switch self {
            case .missingDetails:
                return .orange
            }
        }

        var bannerText: String {
            switch self {
            case .missingDetails:
                return NSLocalizedString(
                    "loads.overview.status.missing_details.banner",
                    bundle: .main,
                    value: "Finish configuring your loads",
                    comment: "Short banner text describing loads that need additional details"
                )
            }
        }
    }

    private struct LoadStatusDetail {
        let title: String
        let message: String
    }

    private func metricBadge(label: String, value: String, tint: Color) -> some View {
        VStack(alignment: .leading, spacing: 2) {
            Text(label.uppercased())
                .font(.caption2)
                .fontWeight(.medium)
                .foregroundStyle(.secondary)
            Text(value)
                .font(.subheadline.weight(.semibold))
                .foregroundStyle(tint)
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 8)
        .background(
            RoundedRectangle(cornerRadius: 10, style: .continuous)
                .fill(tint.opacity(0.12))
        )
    }

    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 handlePrimaryAction() {
        switch selectedComponentTab {
        case .components:
            createNewLoad()
        case .batteries:
            startBatteryConfiguration()
        case .chargers:
            break
        }
    }
    
    private func createNewLoad() {
        let newLoad = SystemComponentsPersistence.createDefaultLoad(
            for: system,
            in: modelContext,
            existingLoads: savedLoads,
            existingBatteries: savedBatteries
        )
        newLoadToEdit = newLoad
    }

    private func startBatteryConfiguration() {
        batteryDraft = SystemComponentsPersistence.makeBatteryDraft(
            for: system,
            existingLoads: savedLoads,
            existingBatteries: savedBatteries
        )
    }
    
    private func saveBattery(_ configuration: BatteryConfiguration) {
        SystemComponentsPersistence.saveBattery(
            configuration,
            for: system,
            existingBatteries: savedBatteries,
            in: modelContext
        )
    }
    
    private func editBattery(_ battery: SavedBattery) {
        batteryDraft = BatteryConfiguration(savedBattery: battery, system: system)
    }

    private func deleteBatteries(_ offsets: IndexSet) {
        withAnimation {
            SystemComponentsPersistence.deleteBatteries(
                at: offsets,
                from: savedBatteries,
                in: modelContext
            )
        }
    }

    private func addComponent(_ item: ComponentLibraryItem) {
        let newLoad = SystemComponentsPersistence.createLoad(
            from: item,
            for: system,
            in: modelContext,
            existingLoads: savedLoads,
            existingBatteries: savedBatteries
        )
        newLoadToEdit = newLoad
    }
    
    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!
    }

    private enum ComponentTab: Hashable {
        case components
        case batteries
        case chargers
    }
}
