
// Service: VClaim (vclaim)
// Description: BPJS VClaim service for eligibility and SEP management

package handlers

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

	"api-service/internal/config"
	"api-service/internal/models"
	"api-service/internal/models/vclaim/peserta"
	"api-service/internal/models/vclaim/sep"
	"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,
	}
}


// GetPESERTABYNIK godoc
// @Summary      Get PesertaBynik data
// @Description  Get participant eligibility information by NIK
// @Tags         vclaim,peserta,nik
// @Accept       json
// @Produce      json

// @Param        X-Request-ID    header    string                          false  "Request ID for tracking"

// @Param        nik           path      string                          true   "nik" example("example_value")

// @Success      200             {object}  peserta.PesertaResponse "Successfully retrieved PesertaBynik data"
// @Failure      400             {object}  models.ErrorResponseBpjs        "Bad request - invalid parameters"
// @Failure      401             {object}  models.ErrorResponseBpjs        "Unauthorized - invalid API credentials"
// @Failure      404             {object}  models.ErrorResponseBpjs        "Not found - PesertaBynik not found"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /peserta/nik/:nik [get]
func (h *VClaimHandler) GetPesertaBynik(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)
	}

	
	h.logger.Info("Processing GetPesertaBynik request", map[string]interface{}{
		"request_id": requestID,
		"endpoint":   "/peserta/nik/:nik",
		
		"nik": c.Param("nik"),
		
	})
	

	// Extract path parameters
	
	nik := c.Param("nik")
	if nik == "" {
		
		h.logger.Error("Missing required parameter nik", map[string]interface{}{
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Missing required parameter nik",
			RequestID: requestID,
		})
		return
	}
	

	// Call service method
	var response peserta.PesertaResponse
	
	endpoint := "/peserta/nik/:nik"
	
	endpoint = strings.Replace(endpoint, ":nik", nik, 1)
	
	err := h.service.Get(ctx, endpoint, &response)
	
	if err != nil {
		
		h.logger.Error("Failed to get PesertaBynik", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Ensure response has proper fields
	response.Status = "success"
	response.RequestID = requestID
	c.JSON(http.StatusOK, response)
}









// GetPESERTABYNOKARTU godoc
// @Summary      Get PesertaBynokartu data
// @Description  Get participant eligibility information by card number
// @Tags         vclaim,peserta,nokartu
// @Accept       json
// @Produce      json

// @Param        X-Request-ID    header    string                          false  "Request ID for tracking"

// @Param        nokartu           path      string                          true   "nokartu" example("example_value")

// @Success      200             {object}  peserta.PesertaResponse "Successfully retrieved PesertaBynokartu data"
// @Failure      400             {object}  models.ErrorResponseBpjs        "Bad request - invalid parameters"
// @Failure      401             {object}  models.ErrorResponseBpjs        "Unauthorized - invalid API credentials"
// @Failure      404             {object}  models.ErrorResponseBpjs        "Not found - PesertaBynokartu not found"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /peserta/:nokartu [get]
func (h *VClaimHandler) GetPesertaBynokartu(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)
	}

	
	h.logger.Info("Processing GetPesertaBynokartu request", map[string]interface{}{
		"request_id": requestID,
		"endpoint":   "/peserta/:nokartu",
		
		"nokartu": c.Param("nokartu"),
		
	})
	

	// Extract path parameters
	
	nokartu := c.Param("nokartu")
	if nokartu == "" {
		
		h.logger.Error("Missing required parameter nokartu", map[string]interface{}{
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Missing required parameter nokartu",
			RequestID: requestID,
		})
		return
	}
	

	// Call service method
	var response peserta.PesertaResponse
	
	endpoint := "/peserta/:nokartu"
	
	endpoint = strings.Replace(endpoint, ":nokartu", nokartu, 1)
	
	err := h.service.Get(ctx, endpoint, &response)
	
	if err != nil {
		
		h.logger.Error("Failed to get PesertaBynokartu", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Ensure response has proper fields
	response.Status = "success"
	response.RequestID = requestID
	c.JSON(http.StatusOK, response)
}









// GetSEPSEP godoc
// @Summary      Get SepSep data
// @Description  Manage SEP (Surat Eligibilitas Peserta)
// @Tags         vclaim,sep
// @Accept       json
// @Produce      json

// @Param        X-Request-ID    header    string                          false  "Request ID for tracking"

// @Param        nosep           path      string                          true   "nosep" example("example_value")

// @Success      200             {object}  sep.SepResponse "Successfully retrieved SepSep data"
// @Failure      400             {object}  models.ErrorResponseBpjs        "Bad request - invalid parameters"
// @Failure      401             {object}  models.ErrorResponseBpjs        "Unauthorized - invalid API credentials"
// @Failure      404             {object}  models.ErrorResponseBpjs        "Not found - SepSep not found"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /sep/:nosep [get]
func (h *VClaimHandler) GetSepSep(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)
	}

	
	h.logger.Info("Processing GetSepSep request", map[string]interface{}{
		"request_id": requestID,
		"endpoint":   "/sep/:nosep",
		
		"nosep": c.Param("nosep"),
		
	})
	

	// Extract path parameters
	
	nosep := c.Param("nosep")
	if nosep == "" {
		
		h.logger.Error("Missing required parameter nosep", map[string]interface{}{
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Missing required parameter nosep",
			RequestID: requestID,
		})
		return
	}
	

	// Call service method
	var response sep.SepResponse
	
	endpoint := "/sep/:nosep"
	
	endpoint = strings.Replace(endpoint, ":nosep", nosep, 1)
	
	err := h.service.Get(ctx, endpoint, &response)
	
	if err != nil {
		
		h.logger.Error("Failed to get SepSep", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Ensure response has proper fields
	response.Status = "success"
	response.RequestID = requestID
	c.JSON(http.StatusOK, response)
}



// CreateSEPSEP godoc
// @Summary      Create new SepSep
// @Description  Manage SEP (Surat Eligibilitas Peserta)
// @Tags         vclaim,sep
// @Accept       json
// @Produce      json

// @Param        X-Request-ID    header    string                          false  "Request ID for tracking"
// @Param        request         body      sep.SepRequest     true   "SepSep data"
// @Success      201             {object}  sep.SepResponse "Successfully created SepSep"
// @Failure      400             {object}  models.ErrorResponseBpjs        "Bad request - invalid request body or validation error"
// @Failure      401             {object}  models.ErrorResponseBpjs        "Unauthorized - invalid API credentials"
// @Failure      409             {object}  models.ErrorResponseBpjs        "Conflict - SepSep already exists"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /sep [post]
func (h *VClaimHandler) CreateSepSep(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)
	}

	
	h.logger.Info("Processing CreateSepSep request", map[string]interface{}{
		"request_id": requestID,
	})
	

	var req sep.SepRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		
		h.logger.Error("Invalid request body", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			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", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Validation failed: " + err.Error(),
			RequestID: requestID,
		})
		return
	}

	// Call service method
	var response sep.SepResponse
	err := h.service.Post(ctx, "/sep", &req, &response)
	if err != nil {
		
		h.logger.Error("Failed to create SepSep", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Ensure response has proper fields
	response.Status = "success"
	response.RequestID = requestID
	c.JSON(http.StatusCreated, response)
}



// UpdateSEPSEP godoc
// @Summary      Update existing SepSep
// @Description  Manage SEP (Surat Eligibilitas Peserta)
// @Tags         vclaim,sep
// @Accept       json
// @Produce      json

// @Param        X-Request-ID    header    string                          false  "Request ID for tracking"

// @Param        nosep           path      string                          true   "nosep" example("example_value")

// @Param        request         body      sep.SepRequest     true   "SepSep data"
// @Success      200             {object}  sep.SepResponse "Successfully updated SepSep"
// @Failure      400             {object}  models.ErrorResponseBpjs        "Bad request - invalid parameters or request body"
// @Failure      401             {object}  models.ErrorResponseBpjs        "Unauthorized - invalid API credentials"
// @Failure      404             {object}  models.ErrorResponseBpjs        "Not found - SepSep not found"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /sep/:nosep [put]
func (h *VClaimHandler) UpdateSepSep(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)
	}

	
	h.logger.Info("Processing UpdateSepSep request", map[string]interface{}{
		"request_id": requestID,
	})
	

	
	nosep := c.Param("nosep")
	if nosep == "" {
		
		h.logger.Error("Missing required parameter nosep", map[string]interface{}{
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Missing required parameter nosep",
			RequestID: requestID,
		})
		return
	}
	

	var req sep.SepRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		
		h.logger.Error("Invalid request body", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			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", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Validation failed: " + err.Error(),
			RequestID: requestID,
		})
		return
	}

	// Call service method
	var response sep.SepResponse
	
	endpoint := "/sep/:nosep"
	
	endpoint = strings.Replace(endpoint, ":nosep", nosep, 1)
	
	err := h.service.Put(ctx, endpoint, &req, &response)
	
	if err != nil {
		
		h.logger.Error("Failed to update SepSep", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Ensure response has proper fields
	response.Status = "success"
	response.RequestID = requestID
	c.JSON(http.StatusOK, response)
}



// DeleteSEPSEP godoc
// @Summary      Delete existing SepSep
// @Description  Manage SEP (Surat Eligibilitas Peserta)
// @Tags         vclaim,sep
// @Accept       json
// @Produce      json

// @Param        X-Request-ID    header    string                          false  "Request ID for tracking"

// @Param        nosep           path      string                          true   "nosep" example("example_value")

// @Success      200             {object}  sep.SepResponse "Successfully deleted SepSep"
// @Failure      400             {object}  models.ErrorResponseBpjs        "Bad request - invalid parameters"
// @Failure      401             {object}  models.ErrorResponseBpjs        "Unauthorized - invalid API credentials"
// @Failure      404             {object}  models.ErrorResponseBpjs        "Not found - SepSep not found"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /sep/:nosep [delete]
func (h *VClaimHandler) DeleteSepSep(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)
	}

	
	h.logger.Info("Processing DeleteSepSep request", map[string]interface{}{
		"request_id": requestID,
	})
	

	
	nosep := c.Param("nosep")
	if nosep == "" {
		
		h.logger.Error("Missing required parameter nosep", map[string]interface{}{
			"request_id": requestID,
		})
		
		c.JSON(http.StatusBadRequest, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Missing required parameter nosep",
			RequestID: requestID,
		})
		return
	}
	

	// Call service method
	var response sep.SepResponse
	
	endpoint := "/sep/:nosep"
	
	endpoint = strings.Replace(endpoint, ":nosep", nosep, 1)
	
	err := h.service.Delete(ctx, endpoint, &response)
	
	if err != nil {
		
		h.logger.Error("Failed to delete SepSep", map[string]interface{}{
			"error":      err.Error(),
			"request_id": requestID,
		})
		
		c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
			Status:    "error",
			Message:   "Internal server error",
			RequestID: requestID,
		})
		return
	}

	// Ensure response has proper fields
	response.Status = "success"
	response.RequestID = requestID
	c.JSON(http.StatusOK, response)
}


