package middleware

import (
	"fmt"
	"net/http"
	"time"

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

// TTL_LEGACY_ROUTES defines the time-to-live for legacy routes before they are removed.
const TTL_LEGACY_ROUTES = 30 * 24 * time.Hour // 30 days

// DeprecationInfo contient les informations de dépréciation d'un endpoint
// INT-020: Structure pour gérer la dépréciation des endpoints
type DeprecationInfo struct {
	Deprecated   bool      // Si l'endpoint est déprécié
	SunsetDate   time.Time // Date de fin de support (quand l'endpoint sera supprimé)
	Replacement  string    // Endpoint de remplacement recommandé (ex: "/api/v1/health")
	MigrationURL string    // URL vers le guide de migration
	Reason       string    // Raison de la dépréciation
}

// DeprecationWarning returns a Gin middleware that adds deprecation headers
// and logs a warning for requests to legacy routes.
// INT-020: Amélioration du middleware de dépréciation avec support de dates personnalisées
func DeprecationWarning(logger *zap.Logger) gin.HandlerFunc {
	return DeprecationWarningWithInfo(logger, DeprecationInfo{
		Deprecated:   true,
		SunsetDate:   time.Now().Add(TTL_LEGACY_ROUTES),
		Replacement:  "/api/v1/*",
		MigrationURL: "https://www.veza.app/api/v1/migration-guide",
		Reason:       "Legacy route - please migrate to /api/v1/* equivalent",
	})
}

// DeprecationWarningWithInfo returns a Gin middleware with custom deprecation information
// INT-020: Permet de spécifier des informations de dépréciation personnalisées
func DeprecationWarningWithInfo(logger *zap.Logger, info DeprecationInfo) gin.HandlerFunc {
	if !info.Deprecated {
		// Si l'endpoint n'est pas déprécié, retourner un middleware no-op
		return func(c *gin.Context) {
			c.Next()
		}
	}

	sunsetDateStr := info.SunsetDate.Format(time.RFC1123)
	deprecationDateStr := time.Now().Format(time.RFC1123)

	return func(c *gin.Context) {
		// INT-020: Log un warning pour chaque accès à un endpoint déprécié
		logger.Warn(
			"Access to deprecated endpoint",
			zap.String("method", c.Request.Method),
			zap.String("path", c.Request.URL.Path),
			zap.String("deprecation_date", deprecationDateStr),
			zap.String("sunset_date", sunsetDateStr),
			zap.String("replacement", info.Replacement),
			zap.String("reason", info.Reason),
			zap.String("action", fmt.Sprintf("Please migrate to %s before %s", info.Replacement, sunsetDateStr)),
		)

		// INT-020: Ajouter les headers de dépréciation standardisés (RFC 8594)
		// Deprecated header (RFC 8594)
		c.Header("Deprecated", "true")

		// Sunset header (RFC 8594) - date de fin de support
		c.Header("Sunset", sunsetDateStr)

		// Link header pour le guide de migration
		if info.MigrationURL != "" {
			c.Header("Link", fmt.Sprintf("<%s>; rel=\"deprecation\"", info.MigrationURL))
		}

		// X-API-Deprecated header (custom, pour compatibilité)
		c.Header("X-API-Deprecated", "true")

		// X-API-Sunset header (custom)
		c.Header("X-API-Sunset", sunsetDateStr)

		// X-API-Replacement header (custom) - endpoint de remplacement
		if info.Replacement != "" {
			c.Header("X-API-Replacement", info.Replacement)
		}

		c.Next()
	}
}

// MarkEndpointDeprecated est un helper pour marquer un endpoint comme déprécié dans le router
// INT-020: Helper pour appliquer facilement la dépréciation aux endpoints
func MarkEndpointDeprecated(router *gin.Engine, method, path string, handler gin.HandlerFunc, logger *zap.Logger, info DeprecationInfo) {
	deprecationMW := DeprecationWarningWithInfo(logger, info)
	switch method {
	case http.MethodGet:
		router.GET(path, deprecationMW, handler)
	case http.MethodPost:
		router.POST(path, deprecationMW, handler)
	case http.MethodPut:
		router.PUT(path, deprecationMW, handler)
	case http.MethodDelete:
		router.DELETE(path, deprecationMW, handler)
	case http.MethodPatch:
		router.PATCH(path, deprecationMW, handler)
	default:
		router.Handle(method, path, deprecationMW, handler)
	}
}
