package infra

import (
	"fmt"
	"sort"
	"strings"
)

// GenerateDockerfile genera el texto de un Dockerfile multi-stage para una app Go.
// Stage build: golang:1.23-alpine — descarga dependencias y compila.
// Stage final: alpine:latest — copia el binario, expone el puerto y lo ejecuta.
// Las envVars se inyectan como instrucciones ENV en el stage final.
// Funcion pura: no realiza I/O, solo genera texto.
func GenerateDockerfile(binaryName string, port int, envVars map[string]string) string {
	var sb strings.Builder

	// Stage build
	sb.WriteString("# Stage build\n")
	sb.WriteString("FROM golang:1.23-alpine AS builder\n\n")
	sb.WriteString("WORKDIR /app\n\n")
	sb.WriteString("COPY go.mod go.sum ./\n")
	sb.WriteString("RUN go mod download\n\n")
	sb.WriteString("COPY . .\n")
	sb.WriteString(fmt.Sprintf("RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags=\"-s -w\" -o %s .\n\n", binaryName))

	// Stage final
	sb.WriteString("# Stage final\n")
	sb.WriteString("FROM alpine:latest\n\n")
	sb.WriteString("RUN apk --no-cache add ca-certificates tzdata\n\n")
	sb.WriteString("WORKDIR /app\n\n")
	sb.WriteString(fmt.Sprintf("COPY --from=builder /app/%s .\n\n", binaryName))

	// ENV vars (orden determinista)
	if len(envVars) > 0 {
		keys := make([]string, 0, len(envVars))
		for k := range envVars {
			keys = append(keys, k)
		}
		sort.Strings(keys)
		for _, k := range keys {
			sb.WriteString(fmt.Sprintf("ENV %s=%s\n", k, envVars[k]))
		}
		sb.WriteString("\n")
	}

	if port > 0 {
		sb.WriteString(fmt.Sprintf("EXPOSE %d\n\n", port))
	}

	sb.WriteString(fmt.Sprintf("ENTRYPOINT [\"./%s\"]\n", binaryName))

	return sb.String()
}
