variable "VARIANTS" {
    type = list(string)
    default = ["apache", "fcgi", "frankenphp"]
    description = "Variants to build"
}

variable "IMAGE_NAME" {
    type = string
    default = "codeberg.org/postmill/postmill"

    validation {
        condition = IMAGE_NAME != ""
        error_message = "IMAGE_NAME cannot be empty"
    }
}

variable "ACTIONS_CACHE_URL" {
    type = string
    description = "URL to GitHub Actions cache API (or compatible)"
    default = ""
}

variable "APP_VERSION" {
    type = string
    default = ""
    description = "Version string"
}

variable "APP_BRANCH" {
    type = string
    default = ""
    description = "Branch"
}

variable "SHA" {
    type = string
    description = "Git commit hash"
}

variable "DEFAULT_DEBIAN_VERSION" {
    type = string
    default = "trixie"
}

variable "DEFAULT_PHP_VERSION" {
    type = string
    default = "8.5"
}

variable "DEFAULT_NGINX_VERSION" {
    type = string
    default = "1.30"
}

variable "DEBIAN_VERSIONS" {
    type = list(string)
    default = ["trixie"]
    description = "Debian base images to build on"
}

variable "NGINX_VERSIONS" {
    type = list(string)
    default = ["1.30", "1.31"]
}

variable "OPERATING_SYSTEMS" {
    type = list(string)
    default = flatten(["alpine", DEBIAN_VERSIONS])
    description = "OS base images to build on"
}

variable "PHP_VERSIONS" {
    type = list(string)
    default = ["8.4", "8.5"]
    description = "PHP versions to build"
}

variable "COMPOSER_AUTH_FILE" {
    type = string
    default = ""
}

# Turn v2.2.1 into ["2.2.1", "2.2", "2"]
function "version_hierarchy" {
    params = [version]
    result = flatten([
        # vX.Y.Z-suffix => ["X.Y.Z-suffix"]
        regexall("^v?(\\d+\\.\\d+\\.\\d+-.*)$", version),

        # vX.Y.Z => ["X.Y.Z", "X.Y", "X"]
        regexall("^v?(((\\d+)\\.\\d+)\\.\\d+)$", version),

        # vX.Y => ["X.Y", "X"]
        regexall("^v?((\\d+)\\.\\d+)$", version),

        # vX => ["X"]
        regexall("^v?(\\d+)$", version),
    ])
}

function "gha_cache_from" {
    params = [scope]
    result = ACTIONS_CACHE_URL != "" ? [
        {
            type = "gha"
            scope = "buildkit-${scope}"
        }
    ] : []
}

function "gha_cache_to" {
    params = [scope]
    result = ACTIONS_CACHE_URL != "" ? [
        {
            type = "gha"
            mode = "max"
            scope = "buildkit-${scope}"
        }
    ] : []
}

function "tag_suffix" {
    params = [
        version,
        variant,
        variant_version_prefix,
        variant_version,
        default_variant_version,
        os,
        default_os,
    ]
    result = compact(flatten([
        "${IMAGE_NAME}:${version}-${variant}${variant_version_prefix != "" ? "-${variant_version_prefix}" : ""}${variant_version}-${os}",

        variant_version == default_variant_version ? [
            "${IMAGE_NAME}:${version}-${variant}-${os}",
        ] : [],

        os == default_os ? [
            "${IMAGE_NAME}:${version}-${variant}${variant_version_prefix != "" ? "-${variant_version_prefix}" : ""}${variant_version}",

            variant_version == default_variant_version
                ? "${IMAGE_NAME}:${version}-${variant}"
                : "",
        ] : [],
    ]))
}

group "default" {
    targets = compact([
        sethaselement(VARIANTS, "fcgi") ? "fcgi_php" : "",
        sethaselement(VARIANTS, "fcgi") ? "fcgi_nginx" : "",
        sethaselement(VARIANTS, "frankenphp") ? "frankenphp" : "",
        sethaselement(VARIANTS, "apache") ? "apache" : "",
    ])
}

target "_common" {
    labels = {
        "org.opencontainers.image.description" = "Open source forum engine and link aggregator"
        "org.opencontainers.image.licenses" = "Zlib"
        "org.opencontainers.image.revision" = SHA
        "org.opencontainers.image.source" = "https://codeberg.org/postmill/postmill"
        "org.opencontainers.image.title" = "Postmill"
        "org.opencontainers.image.url" = "https://postmill.xyz/"
        "org.opencontainers.image.vendor" = "postmill.xyz"
        "org.opencontainers.image.version" = APP_VERSION
    }
    secret = flatten([
        (COMPOSER_AUTH_FILE != "") ? [
            {
                type = "file"
                id = "composer_auth"
                src = COMPOSER_AUTH_FILE
            }
        ] : []
    ])
}

target "apache" {
    inherits = ["_common"]
    name = "apache_php_${sanitize(php)}_${os}"
    matrix = {
        php = PHP_VERSIONS
        os = compact([for os in OPERATING_SYSTEMS:
            os != "alpine" ? os : ""])
    }
    args = {
        APP_VERSION = APP_VERSION
        APP_BRANCH = APP_BRANCH
        DEBIAN_VERSION = os
        PHP_VERSION = php
    }
    cache-from = flatten([gha_cache_from("apache_php_${sanitize(php)}_${os}")])
    cache-to = flatten([gha_cache_to("apache_php_${sanitize(php)}_${os}")])
    tags = compact(flatten([
        [for v in version_hierarchy(APP_VERSION):
            tag_suffix(v, "apache", "php", php, DEFAULT_PHP_VERSION, os, DEFAULT_DEBIAN_VERSION)],
    ]))
    target = "apache_debian"
}

target "fcgi_php" {
    inherits = ["_common"]
    name = "fcgi_php_${sanitize(php)}_${os}"
    matrix = {
        php = PHP_VERSIONS
        os = OPERATING_SYSTEMS
    }
    args = {
        APP_VERSION = APP_VERSION
        APP_BRANCH = APP_BRANCH
        DEBIAN_VERSION = os != "alpine" ? os : ""
        PHP_VERSION = php
    }
    cache-from = flatten([gha_cache_from("fcgi_php_${sanitize(php)}_${os}")])
    cache-to = flatten([gha_cache_to("fcgi_php_${sanitize(php)}_${os}")])
    tags = compact(flatten([
        [for v in version_hierarchy(APP_VERSION):
            tag_suffix(v, "fcgi-php", "", php, DEFAULT_PHP_VERSION, os, "alpine")],
    ]))
    target = "fcgi_php_${os == "alpine" ? "alpine" : "debian"}"
}

target "fcgi_nginx" {
    inherits = ["_common"]
    name = "fcgi_nginx_${sanitize(nginx)}_${os}"
    matrix = {
        nginx = NGINX_VERSIONS
        os = OPERATING_SYSTEMS
    }
    args = {
        DEBIAN_VERSION = os != "alpine" ? os : ""
        NGINX_VERSION = nginx
        PHP_VERSION = DEFAULT_PHP_VERSION
    }
    cache-from = flatten([gha_cache_from("fcgi_nginx_${sanitize(nginx)}_${os}")])
    cache-to = flatten([gha_cache_to("fcgi_nginx_${sanitize(nginx)}_${os}")])
    tags = compact(flatten([
        for v in version_hierarchy(APP_VERSION): [
            nginx == DEFAULT_NGINX_VERSION ? [
                for n in version_hierarchy(nginx):
                    tag_suffix(v, "fcgi-nginx", "", n, DEFAULT_NGINX_VERSION, os, "alpine")
            ] : [
                tag_suffix(v, "fcgi-nginx", "", nginx, DEFAULT_NGINX_VERSION, os, "alpine")
            ]
        ]
    ]))
    target = "fcgi_nginx_${os == "alpine" ? "alpine" : "debian"}"
}

target "frankenphp" {
    inherits = ["_common"]
    name = "frankenphp${sanitize(frankenphp)}_php${sanitize(php)}_${os}"
    matrix = {
        frankenphp = ["1"]
        os = OPERATING_SYSTEMS
        php = PHP_VERSIONS
    }
    args = {
        APP_VERSION = APP_VERSION
        APP_BRANCH = APP_BRANCH
        DEBIAN_VERSION = os != "alpine" ? os : ""
        PHP_VERSION = php
    }
    cache-from = flatten([gha_cache_from("frankenphp${sanitize(frankenphp)}_php${sanitize(php)}_${os}")])
    cache-to = flatten([gha_cache_to("frankenphp${sanitize(frankenphp)}_php${sanitize(php)}_${os}")])
    tags = compact(flatten([
        [for v in version_hierarchy(APP_VERSION):
            tag_suffix(v, "frankenphp", "php", php, DEFAULT_PHP_VERSION, os, DEFAULT_DEBIAN_VERSION)],
    ]))
    target = "frankenphp_${os == "alpine" ? "alpine" : "debian"}"
}
