import SwiftUI

struct BatteriesView: View {
    let system: ElectricalSystem
    let batteries: [SavedBattery]
    let onEdit: (SavedBattery) -> Void
    let onDelete: (IndexSet) -> Void

    private enum BankStatus: Identifiable {
        case voltage(target: Double, mismatchedCount: Int)
        case capacity(target: Double, mismatchedCount: Int)

        var id: String {
            switch self {
            case .voltage: return "voltage"
            case .capacity: return "capacity"
            }
        }

        var symbol: String {
            switch self {
            case .voltage: return "exclamationmark.triangle.fill"
            case .capacity: return "exclamationmark.circle.fill"
            }
        }

        var tint: Color {
            switch self {
            case .voltage: return .red
            case .capacity: return .orange
            }
        }

        var bannerText: String {
            switch self {
            case .voltage:
                return String(
                    localized: "battery.bank.banner.voltage",
                    bundle: .main,
                    comment: "Short banner text describing a voltage mismatch"
                )
            case .capacity:
                return String(
                    localized: "battery.bank.banner.capacity",
                    bundle: .main,
                    comment: "Short banner text describing a capacity mismatch"
                )
            }
        }
    }

    private let voltageTolerance: Double = 0.05
    private let capacityTolerance: Double = 0.5
    @State private var activeStatus: BankStatus?

    private var bankTitle: String {
        String(
            localized: "battery.bank.header.title",
            bundle: .main,
            comment: "Title for the battery bank summary section"
        )
    }

    private var metricCountLabel: String {
        String(
            localized: "battery.bank.metric.count",
            bundle: .main,
            comment: "Label for number of batteries metric"
        )
    }

    private var metricCapacityLabel: String {
        String(
            localized: "battery.bank.metric.capacity",
            bundle: .main,
            comment: "Label for total capacity metric"
        )
    }

    private var metricEnergyLabel: String {
        String(
            localized: "battery.bank.metric.energy",
            bundle: .main,
            comment: "Label for total energy metric"
        )
    }

    private var badgeVoltageLabel: String {
        String(
            localized: "battery.bank.badge.voltage",
            bundle: .main,
            comment: "Label for voltage badge"
        )
    }

    private var badgeCapacityLabel: String {
        String(
            localized: "battery.bank.badge.capacity",
            bundle: .main,
            comment: "Label for capacity badge"
        )
    }

    private var badgeEnergyLabel: String {
        String(
            localized: "battery.bank.badge.energy",
            bundle: .main,
            comment: "Label for energy badge"
        )
    }

    private var emptyTitle: String {
        String(
            localized: "battery.bank.empty.title",
            bundle: .main,
            comment: "Title shown when no batteries are configured"
        )
    }

    init(
        system: ElectricalSystem,
        batteries: [SavedBattery],
        onEdit: @escaping (SavedBattery) -> Void = { _ in },
        onDelete: @escaping (IndexSet) -> Void = { _ in }
    ) {
        self.system = system
        self.batteries = batteries
        self.onEdit = onEdit
        self.onDelete = onDelete
    }

    var body: some View {
        VStack(spacing: 0) {
            if batteries.isEmpty {
                emptyState
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                summarySection

                List {
                    ForEach(batteries) { battery in
                        Button {
                            onEdit(battery)
                        } label: {
                            batteryRow(for: battery)
                        }
                        .buttonStyle(.plain)
                        .listRowInsets(.init(top: 12, leading: 16, bottom: 12, trailing: 16))
                        .listRowSeparator(.hidden)
                        .listRowBackground(Color.clear)
                    }
                    .onDelete(perform: onDelete)
                }
                .listStyle(.plain)
                .scrollContentBackground(.hidden)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color(.systemGroupedBackground))
        .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 battery bank status alert"
                        )
                    )
                )
            )
        }
    }

    private var summarySection: some View {
        VStack(spacing: 0) {
            VStack(alignment: .leading, spacing: 10) {
                HStack(alignment: .firstTextBaseline) {
                    Text(bankTitle)
                        .font(.headline.weight(.semibold))
                    Spacer()
                }

                ViewThatFits(in: .horizontal) {
                    HStack(spacing: 16) {
                        summaryMetric(
                            icon: "battery.100",
                            label: metricCountLabel,
                            value: "\(batteries.count)",
                            tint: .blue
                        )
                        summaryMetric(
                            icon: "gauge.medium",
                            label: metricCapacityLabel,
                            value: formattedValue(totalCapacity, unit: "Ah"),
                            tint: .orange
                        )
                        summaryMetric(
                            icon: "bolt.circle",
                            label: metricEnergyLabel,
                            value: formattedValue(totalEnergy, unit: "Wh"),
                            tint: .green
                        )
                    }

                    VStack(alignment: .leading, spacing: 12) {
                        summaryMetric(
                            icon: "battery.100",
                            label: metricCountLabel,
                            value: "\(batteries.count)",
                            tint: .blue
                        )
                        summaryMetric(
                            icon: "gauge.medium",
                            label: metricCapacityLabel,
                            value: formattedValue(totalCapacity, unit: "Ah"),
                            tint: .orange
                        )
                        summaryMetric(
                            icon: "bolt.circle",
                            label: metricEnergyLabel,
                            value: formattedValue(totalEnergy, unit: "Wh"),
                            tint: .green
                        )
                    }
                }

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

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

    private func batteryRow(for battery: SavedBattery) -> some View {
        VStack(alignment: .leading, spacing: 14) {
            HStack(spacing: 12) {
                batteryIcon

                VStack(alignment: .leading, spacing: 4) {
                    HStack(alignment: .firstTextBaseline) {
                        Text(battery.name)
                            .font(.body.weight(.medium))
                            .lineLimit(1)
                            .truncationMode(.tail)
                        Spacer()
                        Text(formattedValue(battery.nominalVoltage, unit: "V"))
                            .font(.subheadline)
                            .foregroundStyle(.secondary)
                    }

                    Text(battery.chemistry.displayName)
                        .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)
            }

            HStack(spacing: 12) {
                metricBadge(
                    label: badgeVoltageLabel,
                    value: formattedValue(battery.nominalVoltage, unit: "V"),
                    tint: .orange
                )
                metricBadge(
                    label: badgeCapacityLabel,
                    value: formattedValue(battery.capacityAmpHours, unit: "Ah"),
                    tint: .blue
                )
                metricBadge(
                    label: badgeEnergyLabel,
                    value: formattedValue(battery.energyWattHours, unit: "Wh"),
                    tint: .green
                )
                Spacer()
            }
        }
        .padding(.vertical, 16)
        .padding(.horizontal, 16)
        .background(
            RoundedRectangle(cornerRadius: 18, style: .continuous)
                .fill(Color(.systemBackground))
        )
    }

    private var batteryIcon: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 12, style: .continuous)
                .fill(colorForName(system.colorName))
                .frame(width: 48, height: 48)
            Image(systemName: "battery.100.bolt")
                .font(.system(size: 22, weight: .semibold))
                .foregroundStyle(Color.white)
        }
    }

    private var totalCapacity: Double {
        batteries.reduce(0) { result, battery in
            result + battery.capacityAmpHours
        }
    }

    private var totalEnergy: Double {
        batteries.reduce(0) { result, battery in
            result + battery.energyWattHours
        }
    }

    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 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 func statusBanner(for status: BankStatus) -> 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 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 var emptyState: some View {
        VStack(spacing: 16) {
            Image(systemName: "battery.100")
                .font(.largeTitle)
                .foregroundStyle(.secondary)

            Text(emptyTitle)
                .font(.title3)
                .fontWeight(.semibold)

            Text(emptySubtitle(for: system.name))
                .font(.subheadline)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)
        }
        .padding()
    }

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

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

    private var dominantVoltage: Double? {
        guard batteries.count > 1 else { return nil }
        return dominantValue(
            from: batteries.map { $0.nominalVoltage },
            scale: 0.1
        )
    }

    private var dominantCapacity: Double? {
        guard batteries.count > 1 else { return nil }
        return dominantValue(
            from: batteries.map { $0.capacityAmpHours },
            scale: 1.0
        )
    }

    private func dominantValue(from values: [Double], scale: Double) -> Double? {
        guard !values.isEmpty else { return nil }
        var counts: [Double: Int] = [:]
        var bestKey: Double?
        var bestCount = 0
        for value in values {
            let key = (value / scale).rounded() * scale
            let newCount = (counts[key] ?? 0) + 1
            counts[key] = newCount
            if newCount > bestCount {
                bestCount = newCount
                bestKey = key
            }
        }
        return bestKey
    }

    private var bankStatus: BankStatus? {
        guard batteries.count > 1 else { return nil }

        if let targetVoltage = dominantVoltage {
            let mismatched = batteries.filter { abs($0.nominalVoltage - targetVoltage) > voltageTolerance }
            if !mismatched.isEmpty {
                return .voltage(target: targetVoltage, mismatchedCount: mismatched.count)
            }
        }

        if let targetCapacity = dominantCapacity {
            let mismatched = batteries.filter { abs($0.capacityAmpHours - targetCapacity) > capacityTolerance }
            if !mismatched.isEmpty {
                return .capacity(target: targetCapacity, mismatchedCount: mismatched.count)
            }
        }

        return nil
    }

    private func emptySubtitle(for systemName: String) -> String {
        let format = NSLocalizedString(
            "battery.bank.empty.subtitle",
            tableName: nil,
            bundle: .main,
            value: "Tap the plus button to configure a battery for %@.",
            comment: "Subtitle shown when no batteries are configured"
        )
        return String(format: format, systemName)
    }

    private func detailInfo(for status: BankStatus) -> (title: String, message: String) {
        switch status {
        case let .voltage(target, mismatchedCount):
            let countText = mismatchedCount == 1
                ? NSLocalizedString(
                    "battery.bank.status.single.battery",
                    bundle: .main,
                    value: "One battery",
                    comment: "Singular form describing mismatched battery count"
                )
                : String(
                    format: NSLocalizedString(
                        "battery.bank.status.multiple.batteries",
                        bundle: .main,
                        value: "%d batteries",
                        comment: "Plural form describing mismatched battery count"
                    ),
                    mismatchedCount
                )
            let expected = formattedValue(target, unit: "V")
            let message = String(
                format: NSLocalizedString(
                    "battery.bank.status.voltage.message",
                    bundle: .main,
                    value: "%@ diverges from the bank baseline of %@. Mixing nominal voltages leads to uneven charging and can damage connected chargers or inverters.",
                    comment: "Explanation for voltage mismatch in battery bank"
                ),
                countText,
                expected
            )
            return (
                NSLocalizedString(
                    "battery.bank.status.voltage.title",
                    bundle: .main,
                    value: "Voltage mismatch",
                    comment: "Title for voltage mismatch alert"
                ),
                message
            )
        case let .capacity(target, mismatchedCount):
            let countText = mismatchedCount == 1
                ? NSLocalizedString(
                    "battery.bank.status.single.battery",
                    bundle: .main,
                    value: "One battery",
                    comment: "Singular form describing mismatched battery count"
                )
                : String(
                    format: NSLocalizedString(
                        "battery.bank.status.multiple.batteries",
                        bundle: .main,
                        value: "%d batteries",
                        comment: "Plural form describing mismatched battery count"
                    ),
                    mismatchedCount
                )
            let expected = formattedValue(target, unit: "Ah")
            let message = String(
                format: NSLocalizedString(
                    "battery.bank.status.capacity.message",
                    bundle: .main,
                    value: "%@ uses a different capacity than the dominant bank size of %@. Mismatched capacities cause uneven discharge and premature wear.",
                    comment: "Explanation for capacity mismatch in battery bank"
                ),
                countText,
                expected
            )
            return (
                NSLocalizedString(
                    "battery.bank.status.capacity.title",
                    bundle: .main,
                    value: "Capacity mismatch",
                    comment: "Title for capacity mismatch alert"
                ),
                message
            )
        }
    }
}

private enum BatteriesViewPreviewData {
    static let system = ElectricalSystem(name: "Preview System", iconName: "bolt", colorName: "green")
    static let batteries: [SavedBattery] = [
        SavedBattery(
            name: "House Bank",
            nominalVoltage: 12.8,
            capacityAmpHours: 200,
            chemistry: .lithiumIronPhosphate,
            system: system
        ),
        SavedBattery(
            name: "Starter Battery",
            nominalVoltage: 12.0,
            capacityAmpHours: 90,
            chemistry: .agm,
            system: system
        )
    ]
}

#Preview {
    BatteriesView(
        system: BatteriesViewPreviewData.system,
        batteries: BatteriesViewPreviewData.batteries
    )
}
