package api

import (
	"net/http"

	"api-soap-facturacion/internal/config"
	"api-soap-facturacion/internal/logger"
	"api-soap-facturacion/internal/soap"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/jmoiron/sqlx"
)

// NewRouter configura el router HTTP
func NewRouter(cfg *config.Config, log logger.Logger, db *sqlx.DB, soapClients *soap.Clients) *gin.Engine {
	// Configurar modo de Gin según entorno
	if cfg.App.Environment == "production" {
		gin.SetMode(gin.ReleaseMode)
	}

	// Crear router
	router := gin.New()

	// Configurar middleware
	router.Use(gin.Recovery())
	router.Use(LoggerMiddleware(log))
	router.Use(RequestIDMiddleware())
	router.Use(CORSMiddleware())

	// Configurar manejadores
	handler := NewHandler(cfg, log, db, soapClients)

	// Rutas de salud
	router.GET("/health", handler.HealthCheck)

	// Rutas API
	api := router.Group("/api/v1")
	{
		// API1
		api1 := api.Group("/api1")
		{
			api1.POST("/get-data", handler.API1GetData)
		}

		// API2
		api2 := api.Group("/api2")
		{
			api2.POST("/process-transaction", handler.API2ProcessTransaction)
		}

		// Parámetros
		params := api.Group("/parameters")
		{
			params.GET("", handler.GetAllParameters)
			params.GET("/:key", handler.GetParameter)
			params.PUT("/:key", handler.UpdateParameter)
		}
	}

	return router
}

// LoggerMiddleware configura el middleware de logging
func LoggerMiddleware(log logger.Logger) gin.HandlerFunc {
	return func(c *gin.Context) {
		// Antes de la solicitud
		path := c.Request.URL.Path
		method := c.Request.Method
		requestID := c.GetHeader("X-Request-ID")

		// Crear logger para esta solicitud
		reqLogger := log.With(
			logger.NewField("request_id", requestID),
			logger.NewField("path", path),
			logger.NewField("method", method),
		)

		// Almacenar logger en el contexto
		c.Set("logger", reqLogger)

		reqLogger.Info("Solicitud iniciada")

		// Procesar solicitud
		c.Next()

		// Después de la solicitud
		status := c.Writer.Status()
		reqLogger.Info("Solicitud completada",
			logger.NewField("status", status),
		)
	}
}

// RequestIDMiddleware genera un ID único para cada solicitud
func RequestIDMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Si no hay ID de solicitud, generar uno
		requestID := c.GetHeader("X-Request-ID")
		if requestID == "" {
			requestID = generateRequestID()
			c.Request.Header.Set("X-Request-ID", requestID)
		}

		// Establecer ID de solicitud en la respuesta
		c.Writer.Header().Set("X-Request-ID", requestID)
		c.Next()
	}
}

// CORSMiddleware configura CORS
func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-Request-ID")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusOK)
			return
		}

		c.Next()
	}
}

// generateRequestID genera un ID único para una solicitud
func generateRequestID() string {
	return "req-" + uuid.New().String()
}
