// Code generated by generate-dynamic-handler.go; DO NOT EDIT.
// Generated at: 2025-08-28 14:59:09
// Service: VClaim (vclaim)
// Description: BPJS VClaim service for eligibility and SEP management

package handlers

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

	"api-service/internal/config"
	"api-service/internal/models/reference"
	services "api-service/internal/services/bpjs"
	"api-service/pkg/logger"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"github.com/google/uuid"
)

// VClaimHandler handles VClaim BPJS services
type VClaimHandler struct {
	service   services.VClaimService
	validator *validator.Validate
	logger    logger.Logger
	config    *config.BpjsConfig
}

// VClaimHandlerConfig contains configuration for VClaimHandler
type VClaimHandlerConfig struct {
	BpjsConfig *config.BpjsConfig
	Logger     logger.Logger
	Validator  *validator.Validate
}

// NewVClaimHandler creates a new VClaimHandler
func NewVClaimHandler(cfg VClaimHandlerConfig) *VClaimHandler {
	return &VClaimHandler{
		service:   services.NewService(*cfg.BpjsConfig),
		validator: cfg.Validator,
		logger:    cfg.Logger,
		config:    cfg.BpjsConfig,
	}
}

// GetPESERTA retrieves Peserta data
// @Summary Get Peserta data
// @Description Get participant eligibility information
// @Tags vclaim,peserta
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param nokartu path string true "Nokartu"
// @Success 200 {object} reference.PesertaResponse
// @Failure 400 {object} reference.ErrorResponse
// @Failure 500 {object} reference.ErrorResponse
// @Router /Peserta/:nokartu [get]
func (h *VClaimHandler) GetPESERTA(c *gin.Context) {
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	// Generate request ID if not present
	requestID := c.GetHeader("X-Request-ID")
	if requestID == "" {
		requestID = uuid.New().String()
		c.Header("X-Request-ID", requestID)
	}
	// Authentication check
	if err := h.authenticateRequest(c); err != nil {
		h.logger.Error("Authentication failed", "error", err.Error(), "request_id", requestID)
		c.JSON(http.StatusUnauthorized, reference.ErrorResponse{
			Status:    "error",
			Message:   "Authentication failed",
			RequestID: requestID,
		})
		return
	}

	// Extract path parameters
	nokartu := c.Param("nokartu")
	if nokartu == "" {
		h.logger.Error("Missing required parameter: nokartu", "request_id", requestID)
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Missing required parameter: nokartu",
			RequestID: requestID,
		})
		return
	}
	// Check cache first
	cacheKey := fmt.Sprintf("vclaim:peserta:%s", nokartu)
	if cached, found := h.getCachedResponse(cacheKey); found {
		h.logger.Info("Cache hit for GetPESERTA", "request_id", requestID, "cache_key", cacheKey)
		c.Header("X-Cache", "HIT")
		c.JSON(http.StatusOK, cached)
		return
	}

	h.logger.Info("Processing GetPESERTA request",
		"request_id", requestID,
		"endpoint", "/Peserta/:nokartu",
		"nokartu", nokartu)

	// Call service method
	result, err := h.service.GetPESERTA(ctx, nokartu)

	if err != nil {
		h.logger.Error("Failed to get Peserta",
			"error", err.Error(),
			"request_id", requestID)
		c.JSON(http.StatusInternalServerError, reference.ErrorResponse{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Prepare response
	response := reference.PesertaResponse{
		Status:    "success",
		Data:      result,
		RequestID: requestID,
	}
	// Cache successful response
	h.setCachedResponse(cacheKey, response, 300)

	c.Header("X-Cache", "MISS")
	c.JSON(http.StatusOK, response)
}

// GetSEP retrieves Sep data
// @Summary Get Sep data
// @Description Manage SEP (Surat Eligibilitas Peserta)
// @Tags vclaim,sep
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param nosep path string true "Nosep"
// @Success 200 {object} reference.SEPResponse
// @Failure 400 {object} reference.ErrorResponse
// @Failure 500 {object} reference.ErrorResponse
// @Router /SEP/:nosep [get]
func (h *VClaimHandler) GetSEP(c *gin.Context) {
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	// Generate request ID if not present
	requestID := c.GetHeader("X-Request-ID")
	if requestID == "" {
		requestID = uuid.New().String()
		c.Header("X-Request-ID", requestID)
	}
	// Authentication check
	if err := h.authenticateRequest(c); err != nil {
		h.logger.Error("Authentication failed", "error", err.Error(), "request_id", requestID)
		c.JSON(http.StatusUnauthorized, reference.ErrorResponse{
			Status:    "error",
			Message:   "Authentication failed",
			RequestID: requestID,
		})
		return
	}

	// Extract path parameters
	nosep := c.Param("nosep")
	if nosep == "" {
		h.logger.Error("Missing required parameter: nosep", "request_id", requestID)
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Missing required parameter: nosep",
			RequestID: requestID,
		})
		return
	}
	// Check cache first
	cacheKey := fmt.Sprintf("vclaim:sep:%s", nosep)
	if cached, found := h.getCachedResponse(cacheKey); found {
		h.logger.Info("Cache hit for GetSEP", "request_id", requestID, "cache_key", cacheKey)
		c.Header("X-Cache", "HIT")
		c.JSON(http.StatusOK, cached)
		return
	}

	h.logger.Info("Processing GetSEP request",
		"request_id", requestID,
		"endpoint", "/SEP/:nosep",
		"nosep", nosep)

	// Call service method
	result, err := h.service.GetSEP(ctx, nosep)

	if err != nil {
		h.logger.Error("Failed to get Sep",
			"error", err.Error(),
			"request_id", requestID)
		c.JSON(http.StatusInternalServerError, reference.ErrorResponse{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Prepare response
	response := reference.SEPResponse{
		Status:    "success",
		Data:      result,
		RequestID: requestID,
	}
	// Cache successful response
	h.setCachedResponse(cacheKey, response, 180)

	c.Header("X-Cache", "MISS")
	c.JSON(http.StatusOK, response)
}

// CreateSEP creates new Sep
// @Summary Create Sep
// @Description Manage SEP (Surat Eligibilitas Peserta)
// @Tags vclaim,sep
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param request body reference.SEPRequest true "Sep data"
// @Success 201 {object} reference.SEPResponse
// @Failure 400 {object} reference.ErrorResponse
// @Failure 500 {object} reference.ErrorResponse
// @Router /sep [post]
func (h *VClaimHandler) CreateSEP(c *gin.Context) {
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	requestID := c.GetHeader("X-Request-ID")
	if requestID == "" {
		requestID = uuid.New().String()
		c.Header("X-Request-ID", requestID)
	}
	// Authentication check
	if err := h.authenticateRequest(c); err != nil {
		h.logger.Error("Authentication failed", "error", err.Error(), "request_id", requestID)
		c.JSON(http.StatusUnauthorized, reference.ErrorResponse{
			Status:    "error",
			Message:   "Authentication failed",
			RequestID: requestID,
		})
		return
	}

	var req reference.SEPRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		h.logger.Error("Invalid request body",
			"error", err.Error(),
			"request_id", requestID)
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Invalid request body: " + err.Error(),
			RequestID: requestID,
		})
		return
	}

	// Validate request
	if err := h.validator.Struct(&req); err != nil {
		h.logger.Error("Validation failed",
			"error", err.Error(),
			"request_id", requestID)
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Validation failed: " + err.Error(),
			RequestID: requestID,
		})
		return
	}

	h.logger.Info("Processing CreateSEP request", "request_id", requestID)

	// Call service method
	result, err := h.service.CreateSEP(ctx, &req)
	if err != nil {
		h.logger.Error("Failed to create Sep",
			"error", err.Error(),
			"request_id", requestID)
		c.JSON(http.StatusInternalServerError, reference.ErrorResponse{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	response := reference.SEPResponse{
		Status:    "success",
		Data:      result,
		RequestID: requestID,
	}

	c.JSON(http.StatusCreated, response)
}

// UpdateSEP updates existing Sep
// @Summary Update Sep
// @Description Manage SEP (Surat Eligibilitas Peserta)
// @Tags vclaim,sep
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param nosep path string true "Nosep"
// @Param request body reference.SEPRequest true "Sep data"
// @Success 200 {object} reference.SEPResponse
// @Failure 400 {object} reference.ErrorResponse
// @Failure 500 {object} reference.ErrorResponse
// @Router /sep/:nosep [put]
func (h *VClaimHandler) UpdateSEP(c *gin.Context) {
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	requestID := c.GetHeader("X-Request-ID")
	if requestID == "" {
		requestID = uuid.New().String()
		c.Header("X-Request-ID", requestID)
	}

	// Extract path parameters
	nosep := c.Param("nosep")
	if nosep == "" {
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Missing required parameter: nosep",
			RequestID: requestID,
		})
		return
	}

	var req reference.SEPRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Invalid request body: " + err.Error(),
			RequestID: requestID,
		})
		return
	}

	if err := h.validator.Struct(&req); err != nil {
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Validation failed: " + err.Error(),
			RequestID: requestID,
		})
		return
	}
	// Invalidate cache
	cacheKey := fmt.Sprintf("vclaim:sep:%s", nosep)
	h.invalidateCache(cacheKey)

	// Call service method
	result, err := h.service.UpdateSEP(ctx, nosep, &req)

	if err != nil {
		h.logger.Error("Failed to update Sep", "error", err.Error(), "request_id", requestID)
		c.JSON(http.StatusInternalServerError, reference.ErrorResponse{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	response := reference.SEPResponse{
		Status:    "success",
		Data:      result,
		RequestID: requestID,
	}

	c.JSON(http.StatusOK, response)
}

// DeleteSEP deletes existing Sep
// @Summary Delete Sep
// @Description Manage SEP (Surat Eligibilitas Peserta)
// @Tags vclaim,sep
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param nosep path string true "Nosep"
// @Success 200 {object} reference.BaseResponse
// @Failure 400 {object} reference.ErrorResponse
// @Failure 500 {object} reference.ErrorResponse
// @Router /sep/:nosep [delete]
func (h *VClaimHandler) DeleteSEP(c *gin.Context) {
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	requestID := c.GetHeader("X-Request-ID")
	if requestID == "" {
		requestID = uuid.New().String()
		c.Header("X-Request-ID", requestID)
	}

	// Extract path parameters
	nosep := c.Param("nosep")
	if nosep == "" {
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Missing required parameter: nosep",
			RequestID: requestID,
		})
		return
	}
	// Invalidate cache
	cacheKey := fmt.Sprintf("vclaim:sep:%s", nosep)
	h.invalidateCache(cacheKey)

	// Call service method
	err := h.service.DeleteSEP(ctx, nosep)

	if err != nil {
		h.logger.Error("Failed to delete Sep", "error", err.Error(), "request_id", requestID)
		c.JSON(http.StatusInternalServerError, reference.ErrorResponse{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	response := reference.BaseResponse{
		Status:    "success",
		Message:   "Sep deleted successfully",
		RequestID: requestID,
	}

	c.JSON(http.StatusOK, response)
}

// GetRUJUKAN retrieves Rujukan data
// @Summary Get Rujukan data
// @Description Get referral information
// @Tags vclaim,rujukan
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param norujukan path string true "Norujukan"
// @Success 200 {object} reference.RujukanResponse
// @Failure 400 {object} reference.ErrorResponse
// @Failure 500 {object} reference.ErrorResponse
// @Router /rujukan/:norujukan [get]
func (h *VClaimHandler) GetRUJUKAN(c *gin.Context) {
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	// Generate request ID if not present
	requestID := c.GetHeader("X-Request-ID")
	if requestID == "" {
		requestID = uuid.New().String()
		c.Header("X-Request-ID", requestID)
	}
	// Authentication check
	if err := h.authenticateRequest(c); err != nil {
		h.logger.Error("Authentication failed", "error", err.Error(), "request_id", requestID)
		c.JSON(http.StatusUnauthorized, reference.ErrorResponse{
			Status:    "error",
			Message:   "Authentication failed",
			RequestID: requestID,
		})
		return
	}

	// Extract path parameters
	norujukan := c.Param("norujukan")
	if norujukan == "" {
		h.logger.Error("Missing required parameter: norujukan", "request_id", requestID)
		c.JSON(http.StatusBadRequest, reference.ErrorResponse{
			Status:    "error",
			Message:   "Missing required parameter: norujukan",
			RequestID: requestID,
		})
		return
	}
	// Check cache first
	cacheKey := fmt.Sprintf("vclaim:rujukan:%s", norujukan)
	if cached, found := h.getCachedResponse(cacheKey); found {
		h.logger.Info("Cache hit for GetRUJUKAN", "request_id", requestID, "cache_key", cacheKey)
		c.Header("X-Cache", "HIT")
		c.JSON(http.StatusOK, cached)
		return
	}

	h.logger.Info("Processing GetRUJUKAN request",
		"request_id", requestID,
		"endpoint", "/rujukan/:norujukan",
		"norujukan", norujukan)

	// Call service method
	result, err := h.service.GetRUJUKAN(ctx, norujukan)

	if err != nil {
		h.logger.Error("Failed to get Rujukan",
			"error", err.Error(),
			"request_id", requestID)
		c.JSON(http.StatusInternalServerError, reference.ErrorResponse{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Prepare response
	response := reference.RujukanResponse{
		Status:    "success",
		Data:      result,
		RequestID: requestID,
	}
	// Cache successful response
	h.setCachedResponse(cacheKey, response, 600)

	c.Header("X-Cache", "MISS")
	c.JSON(http.StatusOK, response)
}

// RegisterRoutes registers all VClaim routes
func (h *VClaimHandler) RegisterRoutes(router *gin.RouterGroup) {

	router.GET("/Peserta/:nokartu", h.GetPESERTA)

	router.GET("/SEP/:nosep", h.GetSEP)
	router.POST("/sep", h.CreateSEP)
	router.PUT("/sep/:nosep", h.UpdateSEP)
	router.DELETE("/sep/:nosep", h.DeleteSEP)

	router.GET("/rujukan/:norujukan", h.GetRUJUKAN)

}

// Helper methods
func (h *VClaimHandler) authenticateRequest(c *gin.Context) error {
	token := c.GetHeader("Authorization")
	if token == "" {
		return fmt.Errorf("missing authorization header")
	}

	if strings.HasPrefix(token, "Bearer ") {
		token = strings.TrimPrefix(token, "Bearer ")
	}

	return h.auth.ValidateToken(token)
}
func (h *VClaimHandler) getCachedResponse(key string) (interface{}, bool) {
	if h.cache == nil {
		return nil, false
	}
	return h.cache.Get(key)
}

func (h *VClaimHandler) setCachedResponse(key string, data interface{}, ttl int) {
	if h.cache == nil {
		return
	}
	h.cache.Set(key, data, time.Duration(ttl)*time.Second)
}

func (h *VClaimHandler) invalidateCache(key string) {
	if h.cache == nil {
		return
	}
	h.cache.Delete(key)
}
