package middleware

import (
	"strings"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// Versioning middleware pour gérer le versioning de l'API
type Versioning struct {
	defaultVersion    string
	supportedVersions []string
	logger            *zap.Logger
}

// NewVersioning crée un nouveau middleware de versioning
func NewVersioning(defaultVersion string) *Versioning {
	return &Versioning{
		defaultVersion:    defaultVersion,
		supportedVersions: []string{"v1", "v2"},
		logger:            zap.L(),
	}
}

// Handle vérifie et extrait la version de l'API depuis l'URL
func (v *Versioning) Handle() gin.HandlerFunc {
	return func(c *gin.Context) {
		path := c.Request.URL.Path

		// Extraire la version depuis /api/v1/ ou /api/v2/
		parts := strings.Split(path, "/")
		if len(parts) > 2 && parts[1] == "api" {
			version := parts[2]

			// Valider que la version est supportée
			if !v.isVersionSupported(version) {
				// Utiliser la version par défaut
				c.Set("api_version", v.defaultVersion)
				c.Header("X-API-Version", v.defaultVersion)

				// Ajouter un header de dépréciation si nécessaire
				if version != "" && version != v.defaultVersion {
					c.Header("X-API-Deprecated", "true")
					c.Header("X-API-Supported-Versions", strings.Join(v.supportedVersions, ", "))
				}
			} else {
				c.Set("api_version", version)
				c.Header("X-API-Version", version)
			}
		} else {
			// Pas de version dans l'URL, utiliser la valeur par défaut
			c.Set("api_version", v.defaultVersion)
			c.Header("X-API-Version", v.defaultVersion)
		}

		c.Next()
	}
}

// isVersionSupported vérifie si une version est supportée
func (v *Versioning) isVersionSupported(version string) bool {
	for _, supported := range v.supportedVersions {
		if version == supported {
			return true
		}
	}
	return false
}

// GetVersion récupère la version de l'API depuis le contexte
func GetVersion(c *gin.Context) string {
	version, exists := c.Get("api_version")
	if !exists {
		return "v1"
	}
	return version.(string)
}

// RequireVersion vérifie que la version spécifiée est utilisée
func (v *Versioning) RequireVersion(requiredVersion string) gin.HandlerFunc {
	return func(c *gin.Context) {
		currentVersion := GetVersion(c)

		if currentVersion != requiredVersion {
			c.JSON(400, gin.H{
				"error":            "API version mismatch",
				"required_version": requiredVersion,
				"provided_version": currentVersion,
			})
			c.Abort()
			return
		}

		c.Next()
	}
}
