//
//  BrewPhpFormula.swift
//  PHP Monitor
//
//  Created by Nico Verbruggen on 17/03/2023.
//  Copyright © 2025 Nico Verbruggen. All rights reserved.
//

import Foundation

struct BrewPhpFormula: Equatable {

    /// The dependency container.
    let container: Container

    /// Name of the formula.
    let name: String

    /// The human readable name for this formula.
    let displayName: String

    /// The version of the formula that is currently installed.
    let installedVersion: String?

    /// The upgrade that is currently available, if it exists.
    let upgradeVersion: String?

    /// Whether this formula is a stable version of PHP.
    let prerelease: Bool

    /// Whether this formula's associated Homebrew file exists.
    var hasFormulaFile: Bool = false

    /// Whether the formula is currently installed.
    var isInstalled: Bool {
        return installedVersion != nil
    }

    init(
        _ container: Container,
        name: String,
        displayName: String,
        installedVersion: String?,
        upgradeVersion: String?,
        prerelease: Bool = false
    ) {
        self.container = container
        self.name = name
        self.displayName = displayName
        self.installedVersion = installedVersion
        self.upgradeVersion = upgradeVersion
        self.prerelease = prerelease
        self.hasFormulaFile = checkFormulaFile()
    }

    /// Whether the formula can be upgraded.
    var hasUpgrade: Bool {
        return upgradeVersion != nil
    }

    /// Whether this formula alias is different.
    var hasUpgradedFormulaAlias: Bool {
        return self.shortVersion == container.phpEnvs.homebrewBrewPhpAlias
        && container.phpEnvs.homebrewBrewPhpAlias != PhpEnvironments.brewPhpAlias
    }

    var unavailableAfterUpgrade: Bool {
        if installedVersion == nil || upgradeVersion == nil {
            return false
        }

        if let installed = try? VersionNumber.parse(self.installedVersion!),
           let upgrade = try? VersionNumber.parse(self.upgradeVersion!) {
            return upgrade.short != installed.short
        }

        return false
    }

    /// The associated Homebrew folder with this PHP formula.
    var homebrewFolder: String {
        var resolved = name
            .replacing("shivammathur/php/", with: "")

        if let alias = PhpEnvironments.brewPhpAlias {
            resolved = resolved.replacing("php@" + alias, with: "php")
        }

        return "\(App.shared.container.paths.optPath)/\(resolved)/bin"
    }

    /// The short version associated with this formula, if installed.
    var shortVersion: String? {
        guard let version = self.installedVersion else {
            return self.displayName.replacing("PHP ", with: "")
        }

        return VersionNumber.make(from: version)?.short ?? nil
    }

    /// A quick variable that you can check to see if the install is unhealthy.
    /// Will report true if no health information is available.
    var healthy: Bool {
        return isHealthy() ?? true
    }

    /**
     Verify whether the formula file exists (sourced via `shivammathur/homebrew-php`).
     If it does not exist, the formula cannot be installed.
     */
    private func checkFormulaFile() -> Bool {
        guard let version = shortVersion else {
            return false
        }

        var path = "\(container.paths.tapPath)/shivammathur/homebrew-php/Formula/php@\(version).rb"

        if let alias = PhpEnvironments.brewPhpAlias {
            path = path.replacing("php@" + alias, with: "php")
        }

        return container.filesystem.fileExists(path)
    }

    /**
     * Determines if this PHP installation is healthy.
     * Uses the cached installation health check as basis.
     */
    public func isHealthy() -> Bool? {
        guard let shortVersion = self.shortVersion else {
            return nil
        }

        return container.phpEnvs.cachedPhpInstallations[shortVersion]?
            .isHealthy ?? nil
    }

    static func == (lhs: BrewPhpFormula, rhs: BrewPhpFormula) -> Bool {
        return lhs.name == rhs.name
            && lhs.displayName == rhs.displayName
            && lhs.installedVersion == rhs.installedVersion
            && lhs.upgradeVersion == rhs.upgradeVersion
            && lhs.prerelease == rhs.prerelease
            && lhs.hasFormulaFile == rhs.hasFormulaFile
    }
}
