package handlers

import (
	// Added for context.Context
	"errors"
	"fmt"
	"net/http"

	"git.linuxforward.com/byop/byop-engine/auth"
	"git.linuxforward.com/byop/byop-engine/dbstore" // Keep for NewAuthHandler, but userStore is not directly used in handlers
	"git.linuxforward.com/byop/byop-engine/models"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10" // Added for validation
)

// AuthHandler handles authentication-related operations
type AuthHandler struct {
	authService auth.Service
	validate    *validator.Validate // Added for validation
}

// NewAuthHandler creates a new AuthHandler
func NewAuthHandler(authService auth.Service, userStore *dbstore.SQLiteStore) *AuthHandler {
	return &AuthHandler{
		authService: authService,
		validate:    validator.New(), // Initialize validator
	}
}

// LoginRequest defines the structure for login requests.
type LoginRequest struct {
	Email    string `json:"email" validate:"required,email"`
	Password string `json:"password" validate:"required"`
}

// Login handles user authentication
func (h *AuthHandler) Login(c *gin.Context) {
	ctx := c.Request.Context() // Propagate context
	var req LoginRequest

	if err := c.ShouldBindJSON(&req); err != nil {
		models.RespondWithError(c, models.NewErrValidation("invalid_request_body", map[string]string{"body": "Invalid request body"}, err))
		return
	}

	fmt.Println("Login request received:", req.Email) // Debugging line to check input

	// Validate input
	if err := h.validate.Struct(req); err != nil {
		validationErrors := models.ExtractValidationErrors(err)
		models.RespondWithError(c, models.NewErrValidation("input_validation_failed", validationErrors, err))
		return
	}

	tokenResp, err := h.authService.Login(ctx, req.Email, req.Password)
	if err != nil {
		if errors.Is(err, auth.ErrInvalidCredentials) || errors.Is(err, auth.ErrUserNotFound) {
			models.RespondWithError(c, models.NewErrUnauthorized("login_failed", err))
		} else {
			models.RespondWithError(c, models.NewErrInternalServer("login_token_generation_failed", err))
		}
		return
	}

	c.JSON(http.StatusOK, tokenResp) // auth.TokenResponse is now the direct response
}

// RefreshTokenRequest defines the structure for refresh token requests.
type RefreshTokenRequest struct {
	RefreshToken string `json:"refresh_token" validate:"required"`
}

// RefreshToken handles token refresh
func (h *AuthHandler) RefreshToken(c *gin.Context) {
	ctx := c.Request.Context() // Propagate context
	var req RefreshTokenRequest

	if err := c.ShouldBindJSON(&req); err != nil {
		models.RespondWithError(c, models.NewErrValidation("invalid_request_body_refresh", map[string]string{"body": "Invalid request body"}, err))
		return
	}

	if err := h.validate.Struct(req); err != nil {
		validationErrors := models.ExtractValidationErrors(err)
		models.RespondWithError(c, models.NewErrValidation("input_validation_failed_refresh", validationErrors, err))
		return
	}

	resp, err := h.authService.RefreshToken(ctx, req.RefreshToken)
	if err != nil {
		if errors.Is(err, auth.ErrInvalidToken) || errors.Is(err, auth.ErrRefreshTokenNotFound) || errors.Is(err, auth.ErrTokenExpired) {
			models.RespondWithError(c, models.NewErrUnauthorized("invalid_refresh_token", err))
		} else {
			models.RespondWithError(c, models.NewErrInternalServer("refresh_token_failed", err))
		}
		return
	}

	c.JSON(http.StatusOK, resp)
}

// LogoutRequest defines the structure for logout requests.
type LogoutRequest struct {
	Token string `json:"token" validate:"required"` // Assuming the client sends the token to be invalidated
}

// Logout handles user logout
func (h *AuthHandler) Logout(c *gin.Context) {
	ctx := c.Request.Context() // Propagate context
	var req LogoutRequest

	if err := c.ShouldBindJSON(&req); err != nil {
		models.RespondWithError(c, models.NewErrValidation("invalid_request_body_logout", map[string]string{"body": "Invalid request body"}, err))
		return
	}

	if err := h.validate.Struct(req); err != nil {
		validationErrors := models.ExtractValidationErrors(err)
		models.RespondWithError(c, models.NewErrValidation("input_validation_failed_logout", validationErrors, err))
		return
	}

	err := h.authService.Logout(ctx, req.Token)
	if err != nil {
		if errors.Is(err, auth.ErrInvalidToken) {
			models.RespondWithError(c, models.NewErrBadRequest("logout_failed_invalid_token", err))
		} else {
			models.RespondWithError(c, models.NewErrInternalServer("logout_failed", err))
		}
		return
	}

	c.Status(http.StatusNoContent)
}
