package response

import (
	"net/http"
	"time"

	apperrors "veza-backend-api/internal/errors"

	"github.com/gin-gonic/gin"
)

// APIResponse is the unified response envelope
type APIResponse struct {
	Success bool        `json:"success"`
	Data    interface{} `json:"data,omitempty"`
	Error   interface{} `json:"error,omitempty"`
}

// Success sends a successful JSON response
func Success(c *gin.Context, data interface{}, message ...string) {
	response := gin.H{
		"success": true,
		"data":    data,
	}
	if len(message) > 0 {
		response["message"] = message[0]
	}
	c.JSON(http.StatusOK, response)
}

// Created sends a 201 Created response
func Created(c *gin.Context, data interface{}, message ...string) {
	response := gin.H{
		"success": true,
		"data":    data,
	}
	if len(message) > 0 {
		response["message"] = message[0]
	}
	c.JSON(http.StatusCreated, response)
}

// BadRequest sends a 400 Bad Request response
// P0: Migré vers format AppError standardisé
func BadRequest(c *gin.Context, message string) {
	Error(c, http.StatusBadRequest, message)
}

// Unauthorized sends a 401 Unauthorized response
// P0: Migré vers format AppError standardisé
func Unauthorized(c *gin.Context, message string) {
	Error(c, http.StatusUnauthorized, message)
}

// Forbidden sends a 403 Forbidden response
// P0: Migré vers format AppError standardisé
func Forbidden(c *gin.Context, message string) {
	Error(c, http.StatusForbidden, message)
}

// NotFound sends a 404 Not Found response
// P0: Migré vers format AppError standardisé
func NotFound(c *gin.Context, message string) {
	Error(c, http.StatusNotFound, message)
}

// InternalServerError sends a 500 Internal Server Error response
// P0: Migré vers format AppError standardisé
func InternalServerError(c *gin.Context, message string) {
	Error(c, http.StatusInternalServerError, message)
}

// Error sends a custom error response with specified status code
// P0: Migré vers format AppError standardisé
func Error(c *gin.Context, status int, message string) {
	// Convertir status HTTP vers ErrorCode
	var errorCode apperrors.ErrorCode
	switch status {
	case http.StatusBadRequest:
		errorCode = apperrors.ErrCodeValidation
	case http.StatusUnauthorized:
		errorCode = apperrors.ErrCodeInvalidCredentials
	case http.StatusForbidden:
		errorCode = apperrors.ErrCodeForbidden
	case http.StatusNotFound:
		errorCode = apperrors.ErrCodeNotFound
	case http.StatusConflict:
		errorCode = apperrors.ErrCodeConflict
	case http.StatusInternalServerError:
		errorCode = apperrors.ErrCodeInternal
	default:
		errorCode = apperrors.ErrCodeInternal
	}

	appErr := apperrors.New(errorCode, message)
	RespondWithAppError(c, status, appErr)
}

// RespondWithAppError répond avec une AppError au format standardisé
// P0: Helper pour utiliser AppError depuis le package response
func RespondWithAppError(c *gin.Context, statusCode int, appErr *apperrors.AppError) {
	errorData := struct {
		Code      int                     `json:"code"`
		Message   string                  `json:"message"`
		Details   []apperrors.ErrorDetail `json:"details,omitempty"`
		RequestID string                  `json:"request_id,omitempty"`
		Timestamp string                  `json:"timestamp"`
		Context   map[string]interface{}  `json:"context,omitempty"`
	}{
		Code:      int(appErr.Code),
		Message:   appErr.Message,
		Details:   appErr.Details,
		RequestID: c.GetString("request_id"),
		Timestamp: time.Now().UTC().Format(time.RFC3339),
		Context:   appErr.Context,
	}

	// Utiliser la structure APIResponse standardisée
	type APIResponse struct {
		Success bool        `json:"success"`
		Data    interface{} `json:"data,omitempty"`
		Error   interface{} `json:"error,omitempty"`
	}

	c.JSON(statusCode, APIResponse{
		Success: false,
		Data:    nil,
		Error:   errorData,
	})
}

// ValidationError sends a 400 Bad Request response with detailed validation errors
// P0: Migré vers format AppError standardisé
func ValidationError(c *gin.Context, message string, details map[string]string) {
	errorDetails := make([]apperrors.ErrorDetail, 0, len(details))
	for field, msg := range details {
		errorDetails = append(errorDetails, apperrors.ErrorDetail{
			Field:   field,
			Message: msg,
		})
	}
	appErr := apperrors.NewValidationError(message, errorDetails...)
	RespondWithAppError(c, http.StatusBadRequest, appErr)
}
