import Foundation
import MachO

struct MemorySample: Sendable {
    let residentBytes: UInt64
    let physicalFootprintBytes: UInt64
    let virtualBytes: UInt64
}

enum MemoryLog {
    static let detailCacheBuildFootprintLimit: UInt64 = 1_500 * 1_024 * 1_024

    nonisolated static func log(_ event: String, metadata: [String: String] = [:]) {
        let sample = currentSample()
        let metadataText = metadata
            .sorted { $0.key < $1.key }
            .map { "\($0.key)=\($0.value)" }
            .joined(separator: " ")
        let memoryText: String
        if let sample {
            memoryText = "rss=\(format(sample.residentBytes)) footprint=\(format(sample.physicalFootprintBytes)) virtual=\(format(sample.virtualBytes))"
        } else {
            memoryText = "memory=unavailable"
        }

        let line = "[HealthProbeMemory] \(event) \(memoryText)\(metadataText.isEmpty ? "" : " \(metadataText)")"
        print(line)
    }

    nonisolated static func startPulse(_ event: String, metadata: [String: String] = [:], intervalSeconds: UInt64 = 1) -> Task<Void, Never> {
        Task.detached(priority: .background) {
            var previousSample = currentSample()
            var previousTime = Date()
            log("\(event).pulse.start", metadata: metadata)

            while !Task.isCancelled {
                try? await Task.sleep(for: .seconds(intervalSeconds))
                guard !Task.isCancelled else { break }

                let current = currentSample()
                let now = Date()
                var pulseMetadata = metadata

                if let previousSample,
                   let current {
                    let elapsed = max(now.timeIntervalSince(previousTime), 0.001)
                    let footprintDelta = Int64(current.physicalFootprintBytes) - Int64(previousSample.physicalFootprintBytes)
                    let bytesPerSecond = Double(footprintDelta) / elapsed
                    pulseMetadata["footprint_delta"] = signedFormat(footprintDelta)
                    pulseMetadata["footprint_rate"] = "\(signedFormat(Int64(bytesPerSecond)))/s"
                }

                log("\(event).pulse", metadata: pulseMetadata)
                previousSample = current
                previousTime = now
            }

            log("\(event).pulse.stop", metadata: metadata)
        }
    }

    nonisolated static func format(_ bytes: UInt64) -> String {
        ByteCountFormatter.string(fromByteCount: Int64(bytes), countStyle: .memory)
    }

    nonisolated static func isFootprintAtOrAbove(_ bytes: UInt64) -> Bool {
        guard let currentSample = currentSample() else { return false }
        return currentSample.physicalFootprintBytes >= bytes
    }

    nonisolated private static func signedFormat(_ bytes: Int64) -> String {
        if bytes >= 0 {
            return "+\(format(UInt64(bytes)))"
        }
        return "-\(format(UInt64(-bytes)))"
    }

    nonisolated private static func currentSample() -> MemorySample? {
        var info = task_vm_info_data_t()
        var count = mach_msg_type_number_t(MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<integer_t>.size)
        let result = withUnsafeMutablePointer(to: &info) { pointer in
            pointer.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { reboundPointer in
                task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), reboundPointer, &count)
            }
        }

        guard result == KERN_SUCCESS else {
            return nil
        }

        return MemorySample(
            residentBytes: info.resident_size,
            physicalFootprintBytes: info.phys_footprint,
            virtualBytes: info.virtual_size
        )
    }
}
