// Package peserta handles Peserta BPJS services
// Generated on: 2025-09-07 11:01:18
package handlers

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

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

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"github.com/google/uuid"
)
// PesertaHandler handles Peserta BPJS services
type PesertaHandler struct {
	service   services.VClaimService
	validator *validator.Validate
	logger    logger.Logger
	config    config.BpjsConfig
}
// PesertaHandlerConfig contains configuration for PesertaHandler
type PesertaHandlerConfig struct {
	BpjsConfig config.BpjsConfig
	Logger     logger.Logger
	Validator  *validator.Validate
}
// NewPesertaHandler creates a new PesertaHandler
func NewPesertaHandler(cfg PesertaHandlerConfig) *PesertaHandler {
	return &PesertaHandler{
		service:   services.NewService(cfg.BpjsConfig),
		validator: cfg.Validator,
		logger:    cfg.Logger,
		config:    cfg.BpjsConfig,
	}
}


// GetBynik godoc
// @Summary      Get Bynik data
// @Description  Get participant eligibility information by NIK
// @Tags         Peserta
// @Accept       json
// @Produce      json 
// @Security     ApiKeyAuth 
// @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 Bynik 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 - Bynik not found"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /Peserta/nik/:nik [get]
func (h *PesertaHandler) GetBynik(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 GetBynik 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)
    
    resp, err := h.service.GetRawResponse(ctx, endpoint)
    
    if err != nil {
        
        h.logger.Error("Failed to get Bynik", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        
        c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
            Status:    "error",
            Message:   "Internal server error",
            RequestID: requestID,
        })
        return
    }

    // Map the raw response
    response.MetaData = resp.MetaData
    if resp.Response != nil {
        response.Data = &peserta.PesertaData{}
        if respStr, ok := resp.Response.(string); ok {
            // Decrypt the response string
            consID, secretKey, _, tstamp, _ := h.config.SetHeader()
            decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
            if err != nil {
                
                h.logger.Error("Failed to decrypt response", map[string]interface{}{
                    "error":      err.Error(),
                    "request_id": requestID,
                })
                
            } else {
                json.Unmarshal([]byte(decryptedResp), response.Data)
            }
        } else if respMap, ok := resp.Response.(map[string]interface{}); ok {
            // Response is already unmarshaled JSON
            if dataMap, exists := respMap["peserta"]; exists {
                dataBytes, _ := json.Marshal(dataMap)
                json.Unmarshal(dataBytes, response.Data)
            } else {
                // Try to unmarshal the whole response
                respBytes, _ := json.Marshal(resp.Response)
                json.Unmarshal(respBytes, response.Data)
            }
        }
    }

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










// GetBynokartu godoc
// @Summary      Get Bynokartu data
// @Description  Get participant eligibility information by card number
// @Tags         Peserta
// @Accept       json
// @Produce      json 
// @Security     ApiKeyAuth 
// @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 Bynokartu 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 - Bynokartu not found"
// @Failure      500             {object}  models.ErrorResponseBpjs        "Internal server error"
// @Router       /Peserta/nokartu/:nokartu [get]
func (h *PesertaHandler) GetBynokartu(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 GetBynokartu 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)
    
    resp, err := h.service.GetRawResponse(ctx, endpoint)
    
    if err != nil {
        
        h.logger.Error("Failed to get Bynokartu", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        
        c.JSON(http.StatusInternalServerError, models.ErrorResponseBpjs{
            Status:    "error",
            Message:   "Internal server error",
            RequestID: requestID,
        })
        return
    }

    // Map the raw response
    response.MetaData = resp.MetaData
    if resp.Response != nil {
        response.Data = &peserta.PesertaData{}
        if respStr, ok := resp.Response.(string); ok {
            // Decrypt the response string
            consID, secretKey, _, tstamp, _ := h.config.SetHeader()
            decryptedResp, err := services.ResponseVclaim(respStr, consID+secretKey+tstamp)
            if err != nil {
                
                h.logger.Error("Failed to decrypt response", map[string]interface{}{
                    "error":      err.Error(),
                    "request_id": requestID,
                })
                
            } else {
                json.Unmarshal([]byte(decryptedResp), response.Data)
            }
        } else if respMap, ok := resp.Response.(map[string]interface{}); ok {
            // Response is already unmarshaled JSON
            if dataMap, exists := respMap["peserta"]; exists {
                dataBytes, _ := json.Marshal(dataMap)
                json.Unmarshal(dataBytes, response.Data)
            } else {
                // Try to unmarshal the whole response
                respBytes, _ := json.Marshal(resp.Response)
                json.Unmarshal(respBytes, response.Data)
            }
        }
    }

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








