import Foundation

struct OutdatedPackage: Codable, Equatable {
    let name: String
    let installedVersions: [String]
    let currentVersion: String

    /// Menu label, e.g. "wget 1.21 → 1.22"
    var label: String {
        let installed = installedVersions.joined(separator: ", ")
        return "\(name) \(installed) → \(currentVersion)"
    }
}

struct OutdatedPackages: Codable, Equatable {
    let formulae: [OutdatedPackage]
    let casks: [OutdatedPackage]

    var all: [OutdatedPackage] {
        formulae + casks
    }

    var isEmpty: Bool {
        formulae.isEmpty && casks.isEmpty
    }

    var count: Int {
        formulae.count + casks.count
    }

    static let none = OutdatedPackages(formulae: [], casks: [])
}

enum BrewParser {
    /// Parses `brew outdated --json` output. Returns .none for anything
    /// undecodable (brew error text, empty output) — same effect as an
    /// empty result, and the raw output is already in the log window.
    static func parseOutdatedJSON(_ output: String) -> OutdatedPackages {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase // installed_versions → installedVersions

        guard let data = output.data(using: .utf8),
              let parsed = try? decoder.decode(OutdatedPackages.self, from: data)
        else {
            return .none
        }
        return parsed
    }

    static func parseVersion(_ output: String) -> String {
        output.split(separator: "\n").first.map(String.init) ?? "Unknown"
    }
}
