package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// BpjsHandlerData contains template data for BPJS handler generation
type BpjsHandlerData struct {
	Name           string
	NameLower      string
	NameUpper      string
	Category       string
	CategoryPath   string
	ModuleName     string
	HasGet         bool
	HasPost        bool
	HasPut         bool
	HasDelete      bool
	GetEndpoint    string
	PostEndpoint   string
	PutEndpoint    string
	DeleteEndpoint string
	Timestamp      string
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run generate-bpjs-handler.go [category/]entity [methods]")
		fmt.Println("Examples:")
		fmt.Println(" go run generate-bpjs-handler.go vclaim/sep get post put delete")
		fmt.Println(" go run generate-bpjs-handler.go eclaim/klaim get post")
		fmt.Println(" go run generate-bpjs-handler.go peserta get")
		os.Exit(1)
	}

	// Parse entity path
	entityPath := os.Args[1]
	methods := []string{}
	if len(os.Args) > 2 {
		methods = os.Args[2:]
	} else {
		methods = []string{"get", "post", "put", "delete"}
	}

	// Parse category and entity
	var category, entityName string
	if strings.Contains(entityPath, "/") {
		parts := strings.Split(entityPath, "/")
		if len(parts) != 2 {
			fmt.Println("❌ Error: Invalid path format. Use 'category/entity' or just 'entity'")
			os.Exit(1)
		}
		category = parts[0]
		entityName = parts[1]
	} else {
		category = ""
		entityName = entityPath
	}

	// Format names
	entityName = strings.Title(entityName)
	entityLower := strings.ToLower(entityName)
	entityUpper := strings.ToUpper(entityName)

	data := BpjsHandlerData{
		Name:         entityName,
		NameLower:    entityLower,
		NameUpper:    entityUpper,
		Category:     category,
		CategoryPath: category,
		ModuleName:   "api-service",
		Timestamp:    time.Now().Format("2006-01-02 15:04:05"),
	}

	// Set methods and endpoints
	for _, m := range methods {
		switch strings.ToLower(m) {
		case "get":
			data.HasGet = true
			data.GetEndpoint = fmt.Sprintf("%s/{id}", entityUpper)
		case "post":
			data.HasPost = true
			data.PostEndpoint = fmt.Sprintf("%s/2.0/insert", entityUpper)
		case "put":
			data.HasPut = true
			data.PutEndpoint = fmt.Sprintf("%s/2.0/update", entityUpper)
		case "delete":
			data.HasDelete = true
			data.DeleteEndpoint = fmt.Sprintf("%s/2.0/delete", entityUpper)
		}
	}

	// Create directories
	var handlerDir, modelDir string
	if category != "" {
		handlerDir = filepath.Join("internal", "handlers", category)
		modelDir = filepath.Join("internal", "models", category)
	} else {
		handlerDir = filepath.Join("internal", "handlers")
		modelDir = filepath.Join("internal", "models")
	}

	for _, d := range []string{handlerDir, modelDir} {
		if err := os.MkdirAll(d, 0755); err != nil {
			panic(err)
		}
	}

	// Generate files
	generateOptimizedBpjsHandlerFile(data, handlerDir)
	generateOptimizedBpjsModelFile(data, modelDir)
	updateOptimizedBpjsRoutesFile(data)

	fmt.Printf("✅ Successfully generated optimized BPJS handler: %s\n", entityName)
	if category != "" {
		fmt.Printf("📁 Category: %s\n", category)
	}
	fmt.Printf("📁 Handler: %s\n", filepath.Join(handlerDir, entityLower+".go"))
	fmt.Printf("📁 Model: %s\n", filepath.Join(modelDir, entityLower+".go"))
}

// ================= OPTIMIZED HANDLER GENERATION =====================

func generateOptimizedBpjsHandlerFile(data BpjsHandlerData, handlerDir string) {
	var modelsImportPath string
	if data.Category != "" {
		modelsImportPath = data.ModuleName + "/internal/models/" + data.Category
	} else {
		modelsImportPath = data.ModuleName + "/internal/models"
	}

	handlerContent := `package handlers

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

    "` + data.ModuleName + `/internal/config"
    "` + modelsImportPath + `"
    services "` + data.ModuleName + `/internal/services/bpjs"
    "` + data.ModuleName + `/pkg/logger"

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

// ` + data.Name + `Handler handles ` + data.NameLower + ` BPJS services with optimized error handling and logging
type ` + data.Name + `Handler struct {
    service   services.VClaimService
    validator *validator.Validate
    logger    logger.Logger
    config    *config.BpjsConfig
}

// HandlerConfig contains configuration for ` + data.Name + `Handler
type ` + data.Name + `HandlerConfig struct {
    BpjsConfig *config.BpjsConfig
    Logger     logger.Logger
    Validator  *validator.Validate
}

// New` + data.Name + `Handler creates a new optimized ` + data.Name + `Handler
func New` + data.Name + `Handler(cfg *` + data.Name + `HandlerConfig) *` + data.Name + `Handler {
    return &` + data.Name + `Handler{
        service:   services.NewService(*cfg.BpjsConfig),
        validator: cfg.Validator,
        logger:    cfg.Logger,
        config:    cfg.BpjsConfig,
    }
}`

	// Add optimized methods based on flags
	if data.HasPost {
		handlerContent += generateOptimizedBpjsCreateMethod(data)
	}

	if data.HasPut {
		handlerContent += generateOptimizedBpjsUpdateMethod(data)
	}

	if data.HasDelete {
		handlerContent += generateOptimizedBpjsDeleteMethod(data)
	}

	if data.HasGet {
		handlerContent += generateOptimizedBpjsGetMethod(data)
	}

	// Add helper methods
	handlerContent += generateHelperMethods(data)

	writeFile(filepath.Join(handlerDir, data.NameLower+".go"), handlerContent)
}

func generateOptimizedBpjsCreateMethod(data BpjsHandlerData) string {
	var routePath, tagName string
	if data.Category != "" {
		routePath = data.Category + "/" + data.NameLower
		tagName = strings.Title(data.Category) + "-" + strings.Title(data.NameLower)
	} else {
		routePath = data.NameLower
		tagName = strings.Title(data.NameLower)
	}

	return `

// Create` + data.Name + ` creates a new ` + data.Name + ` with comprehensive error handling and validation
// @Summary Create a new ` + data.NameUpper + `
// @Description Create a new ` + data.Name + ` in BPJS system with enhanced validation and logging
// @Tags ` + tagName + `
// @Accept json
// @Produce json
// @Param request body models.` + data.Name + `PostRequest true "` + data.Name + ` creation request"
// @Success 200 {object} models.` + data.Name + `Response "` + data.Name + ` created successfully"
// @Failure 400 {object} models.` + data.Name + `Response "Bad request - validation error"
// @Failure 422 {object} models.` + data.Name + `Response "Unprocessable entity - business logic error"
// @Failure 500 {object} models.` + data.Name + `Response "Internal server error"
// @Router /api/v1/` + routePath + ` [post]
func (h *` + data.Name + `Handler) Create` + data.Name + `(c *gin.Context) {
    requestID := uuid.New().String()
    startTime := time.Now()
    
    h.logger.Info("Creating ` + data.Name + `", map[string]interface{}{
        "request_id": requestID,
        "timestamp":  startTime,
    })

    var req models.` + data.Name + `PostRequest
    req.RequestID = requestID
    req.Timestamp = startTime

    // Bind and validate JSON
    if err := c.ShouldBindJSON(&req); err != nil {
        h.logger.Error("Failed to bind JSON", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        h.sendErrorResponse(c, http.StatusBadRequest, "INVALID_REQUEST_FORMAT", 
            "Format request tidak valid", err.Error(), requestID)
        return
    }

    // Custom validation
    if err := req.Validate(); err != nil {
        h.logger.Error("Custom validation failed", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        h.sendErrorResponse(c, http.StatusBadRequest, "VALIDATION_ERROR", 
            "Validasi gagal", err.Error(), requestID)
        return
    }

    // Struct validation
    if err := h.validator.Struct(&req); err != nil {
        h.logger.Error("Struct validation failed", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        h.sendErrorResponse(c, http.StatusBadRequest, "VALIDATION_ERROR", 
            "Validasi struktur gagal", h.formatValidationError(err), requestID)
        return
    }

    ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
    defer cancel()

    var rawResponse models.BpjsRawResponse
    if err := h.service.Post(ctx, "` + data.PostEndpoint + `", req, &rawResponse); err != nil {
        h.logger.Error("Failed to call BPJS service", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
            "endpoint":   "` + data.PostEndpoint + `",
        })
        
        statusCode, errorCode := h.categorizeError(err)
        h.sendErrorResponse(c, statusCode, errorCode, 
            "Gagal membuat ` + data.Name + `", err.Error(), requestID)
        return
    }

    // Check BPJS response
    if rawResponse.MetaData.Code != "200" {
        h.logger.Warn("BPJS returned error", map[string]interface{}{
            "bpjs_code":    rawResponse.MetaData.Code,
            "bpjs_message": rawResponse.MetaData.Message,
            "request_id":   requestID,
        })
        
        statusCode := h.mapBpjsCodeToHttpStatus(rawResponse.MetaData.Code)
        h.sendErrorResponse(c, statusCode, rawResponse.MetaData.Code, 
            rawResponse.MetaData.Message, "", requestID)
        return
    }

    duration := time.Since(startTime)
    h.logger.Info("` + data.Name + ` created successfully", map[string]interface{}{
        "request_id": requestID,
        "duration":   duration.String(),
    })

    h.sendSuccessResponse(c, "` + data.Name + ` berhasil dibuat", rawResponse.Response, requestID)
}`
}

func generateOptimizedBpjsUpdateMethod(data BpjsHandlerData) string {
	var routePath, tagName string
	if data.Category != "" {
		routePath = data.Category + "/" + data.NameLower
		tagName = strings.Title(data.Category) + "-" + strings.Title(data.NameLower)
	} else {
		routePath = data.NameLower
		tagName = strings.Title(data.NameLower)
	}

	return `

// Update` + data.Name + ` updates an existing ` + data.Name + ` with comprehensive validation
// @Summary Update an existing ` + data.NameUpper + `
// @Description Update an existing ` + data.Name + ` in BPJS system with enhanced validation and logging
// @Tags ` + tagName + `
// @Accept json
// @Produce json
// @Param request body models.` + data.Name + `PutRequest true "` + data.Name + ` update request"
// @Success 200 {object} models.` + data.Name + `Response "` + data.Name + ` updated successfully"
// @Failure 400 {object} models.` + data.Name + `Response "Bad request - validation error"
// @Failure 422 {object} models.` + data.Name + `Response "Unprocessable entity - business logic error"
// @Failure 500 {object} models.` + data.Name + `Response "Internal server error"
// @Router /api/v1/` + routePath + ` [put]
func (h *` + data.Name + `Handler) Update` + data.Name + `(c *gin.Context) {
    requestID := uuid.New().String()
    startTime := time.Now()
    
    h.logger.Info("Updating ` + data.Name + `", map[string]interface{}{
        "request_id": requestID,
        "timestamp":  startTime,
    })

    var req models.` + data.Name + `PutRequest
    req.RequestID = requestID
    req.Timestamp = startTime

    if err := c.ShouldBindJSON(&req); err != nil {
        h.logger.Error("Failed to bind JSON for update", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        h.sendErrorResponse(c, http.StatusBadRequest, "INVALID_REQUEST_FORMAT", 
            "Format request tidak valid", err.Error(), requestID)
        return
    }

    if err := req.Validate(); err != nil {
        h.logger.Error("Update validation failed", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        h.sendErrorResponse(c, http.StatusBadRequest, "VALIDATION_ERROR", 
            "Validasi gagal", err.Error(), requestID)
        return
    }

    if err := h.validator.Struct(&req); err != nil {
        h.logger.Error("Struct validation failed", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        h.sendErrorResponse(c, http.StatusBadRequest, "VALIDATION_ERROR", 
            "Validasi struktur gagal", h.formatValidationError(err), requestID)
        return
    }

    ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
    defer cancel()

    var rawResponse models.BpjsRawResponse
    if err := h.service.Put(ctx, "` + data.PutEndpoint + `", req, &rawResponse); err != nil {
        h.logger.Error("Failed to update ` + data.Name + `", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        
        statusCode, errorCode := h.categorizeError(err)
        h.sendErrorResponse(c, statusCode, errorCode, 
            "Gagal memperbarui ` + data.Name + `", err.Error(), requestID)
        return
    }

    if rawResponse.MetaData.Code != "200" {
        h.logger.Warn("BPJS update returned error", map[string]interface{}{
            "bpjs_code":    rawResponse.MetaData.Code,
            "bpjs_message": rawResponse.MetaData.Message,
            "request_id":   requestID,
        })
        
        statusCode := h.mapBpjsCodeToHttpStatus(rawResponse.MetaData.Code)
        h.sendErrorResponse(c, statusCode, rawResponse.MetaData.Code, 
            rawResponse.MetaData.Message, "", requestID)
        return
    }

    duration := time.Since(startTime)
    h.logger.Info("` + data.Name + ` updated successfully", map[string]interface{}{
        "request_id": requestID,
        "duration":   duration.String(),
    })

    h.sendSuccessResponse(c, "` + data.Name + ` berhasil diperbarui", rawResponse.Response, requestID)
}`
}

func generateOptimizedBpjsDeleteMethod(data BpjsHandlerData) string {
	var routePath, tagName string
	if data.Category != "" {
		routePath = data.Category + "/" + data.NameLower
		tagName = strings.Title(data.Category) + "-" + strings.Title(data.NameLower)
	} else {
		routePath = data.NameLower
		tagName = strings.Title(data.NameLower)
	}

	return `

// Delete` + data.Name + ` deletes an existing ` + data.Name + ` with comprehensive validation
// @Summary Delete an existing ` + data.NameUpper + `
// @Description Delete a ` + data.Name + ` by ID with enhanced validation and logging
// @Tags ` + tagName + `
// @Accept json
// @Produce json
// @Param id path string true "` + data.Name + ` ID"
// @Param user query string true "User identifier"
// @Success 200 {object} models.` + data.Name + `Response "` + data.Name + ` deleted successfully"
// @Failure 400 {object} models.` + data.Name + `Response "Bad request - missing parameters"
// @Failure 422 {object} models.` + data.Name + `Response "Unprocessable entity - business logic error"
// @Failure 500 {object} models.` + data.Name + `Response "Internal server error"
// @Router /api/v1/` + routePath + `/{id} [delete]
func (h *` + data.Name + `Handler) Delete` + data.Name + `(c *gin.Context) {
    requestID := uuid.New().String()
    startTime := time.Now()
    id := c.Param("id")
    user := c.Query("user")

    h.logger.Info("Deleting ` + data.Name + `", map[string]interface{}{
        "request_id": requestID,
        "timestamp":  startTime,
        "id":         id,
        "user":       user,
    })

    // Validate parameters
    if id == "" {
        h.sendErrorResponse(c, http.StatusBadRequest, "MISSING_PARAMETER", 
            "Parameter ID wajib diisi", "", requestID)
        return
    }

    if user == "" {
        h.sendErrorResponse(c, http.StatusBadRequest, "MISSING_PARAMETER", 
            "Parameter user wajib diisi", "", requestID)
        return
    }

    req := models.` + data.Name + `DeleteRequest{
        BaseRequest: models.BaseRequest{
            RequestID: requestID,
            Timestamp: startTime,
        },
        T` + data.Name + `: models.` + data.Name + `DeleteData{
            ID:   id,
            User: user,
        },
    }

    if err := req.Validate(); err != nil {
        h.logger.Error("Delete validation failed", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
        })
        h.sendErrorResponse(c, http.StatusBadRequest, "VALIDATION_ERROR", 
            "Validasi gagal", err.Error(), requestID)
        return
    }

    ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
    defer cancel()

    var rawResponse models.BpjsRawResponse
    if err := h.service.Delete(ctx, "` + data.DeleteEndpoint + `", req); err != nil {
        h.logger.Error("Failed to delete ` + data.Name + `", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
            "id":         id,
        })
        
        statusCode, errorCode := h.categorizeError(err)
        h.sendErrorResponse(c, statusCode, errorCode, 
            "Gagal menghapus ` + data.Name + `", err.Error(), requestID)
        return
    }

    if rawResponse.MetaData.Code != "200" {
        h.logger.Warn("BPJS delete returned error", map[string]interface{}{
            "bpjs_code":    rawResponse.MetaData.Code,
            "bpjs_message": rawResponse.MetaData.Message,
            "request_id":   requestID,
            "id":           id,
        })
        
        statusCode := h.mapBpjsCodeToHttpStatus(rawResponse.MetaData.Code)
        h.sendErrorResponse(c, statusCode, rawResponse.MetaData.Code, 
            rawResponse.MetaData.Message, "", requestID)
        return
    }

    duration := time.Since(startTime)
    h.logger.Info("` + data.Name + ` deleted successfully", map[string]interface{}{
        "request_id": requestID,
        "duration":   duration.String(),
        "id":         id,
    })

    h.sendSuccessResponse(c, "` + data.Name + ` berhasil dihapus", rawResponse.Response, requestID)
}`
}

func generateOptimizedBpjsGetMethod(data BpjsHandlerData) string {
	var routePath, tagName string
	if data.Category != "" {
		routePath = data.Category + "/" + data.NameLower
		tagName = strings.Title(data.Category) + "-" + strings.Title(data.NameLower)
	} else {
		routePath = data.NameLower
		tagName = strings.Title(data.NameLower)
	}

	return `

// Get` + data.Name + ` retrieves ` + data.Name + ` details with comprehensive error handling
// @Summary Get an existing ` + data.NameUpper + `
// @Description Retrieve a ` + data.Name + ` by ID with enhanced validation and logging
// @Tags ` + tagName + `
// @Accept json
// @Produce json
// @Param id path string true "` + data.Name + ` ID"
// @Success 200 {object} models.` + data.Name + `Response "Data ` + data.Name + ` retrieved successfully"
// @Failure 400 {object} models.` + data.Name + `Response "Bad request - invalid ID"
// @Failure 404 {object} models.` + data.Name + `Response "` + data.Name + ` not found"
// @Failure 500 {object} models.` + data.Name + `Response "Internal server error"
// @Router /api/v1/` + routePath + `/{id} [get]
func (h *` + data.Name + `Handler) Get` + data.Name + `(c *gin.Context) {
    requestID := uuid.New().String()
    startTime := time.Now()
    id := c.Param("id")

    h.logger.Info("Getting ` + data.Name + `", map[string]interface{}{
        "request_id": requestID,
        "timestamp":  startTime,
        "id":         id,
    })

    if id == "" {
        h.sendErrorResponse(c, http.StatusBadRequest, "MISSING_PARAMETER", 
            "Parameter ID wajib diisi", "", requestID)
        return
    }

    ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
    defer cancel()

    endpoint := fmt.Sprintf("` + strings.Replace(data.GetEndpoint, "{id}", "%s", 1) + `", id)
    var rawResponse models.BpjsRawResponse

    if err := h.service.Get(ctx, endpoint, &rawResponse); err != nil {
        h.logger.Error("Failed to get ` + data.Name + `", map[string]interface{}{
            "error":      err.Error(),
            "request_id": requestID,
            "id":         id,
        })
        
        statusCode, errorCode := h.categorizeError(err)
        h.sendErrorResponse(c, statusCode, errorCode, 
            "Gagal mengambil data ` + data.Name + `", err.Error(), requestID)
        return
    }

    if rawResponse.MetaData.Code != "200" {
        // Handle specific BPJS error codes
        if rawResponse.MetaData.Code == "201" {
            h.logger.Info("` + data.Name + ` not found", map[string]interface{}{
                "request_id": requestID,
                "id":         id,
            })
            h.sendErrorResponse(c, http.StatusNotFound, "DATA_NOT_FOUND", 
                "Data ` + data.Name + ` tidak ditemukan", rawResponse.MetaData.Message, requestID)
            return
        }

        h.logger.Warn("BPJS get returned error", map[string]interface{}{
            "bpjs_code":    rawResponse.MetaData.Code,
            "bpjs_message": rawResponse.MetaData.Message,
            "request_id":   requestID,
            "id":           id,
        })
        
        statusCode := h.mapBpjsCodeToHttpStatus(rawResponse.MetaData.Code)
        h.sendErrorResponse(c, statusCode, rawResponse.MetaData.Code, 
            rawResponse.MetaData.Message, "", requestID)
        return
    }

    duration := time.Since(startTime)
    h.logger.Info("` + data.Name + ` retrieved successfully", map[string]interface{}{
        "request_id": requestID,
        "duration":   duration.String(),
        "id":         id,
    })

    h.sendSuccessResponse(c, "Data ` + data.Name + ` berhasil diambil", rawResponse.Response, requestID)
}`
}

func generateHelperMethods(data BpjsHandlerData) string {
	return `

// Helper methods for ` + data.Name + `Handler
func (h *` + data.Name + `Handler) sendSuccessResponse(c *gin.Context, message string, data interface{}, requestID string) {
    response := models.` + data.Name + `Response{
        BaseResponse: models.BaseResponse{
            Status:  "success",
            Message: message,
            Data:    data,
            Metadata: &models.ResponseMetadata{
                Timestamp: time.Now(),
                Version:   "2.0",
                RequestID: requestID,
            },
        },
    }
    c.JSON(http.StatusOK, response)
}

func (h *` + data.Name + `Handler) sendErrorResponse(c *gin.Context, statusCode int, errorCode, message, details, requestID string) {
    response := models.` + data.Name + `Response{
        BaseResponse: models.BaseResponse{
            Status:  "error",
            Message: message,
            Error: &models.ErrorResponse{
                Code:    errorCode,
                Message: message,
                Details: details,
            },
            Metadata: &models.ResponseMetadata{
                Timestamp: time.Now(),
                Version:   "2.0",
                RequestID: requestID,
            },
        },
    }
    c.JSON(statusCode, response)
}

func (h *` + data.Name + `Handler) formatValidationError(err error) string {
    if validationErrors, ok := err.(validator.ValidationErrors); ok {
        var messages []string
        for _, e := range validationErrors {
            switch e.Tag() {
            case "required":
                messages = append(messages, fmt.Sprintf("%s wajib diisi", e.Field()))
            case "min":
                messages = append(messages, fmt.Sprintf("%s minimal %s karakter", e.Field(), e.Param()))
            case "max":
                messages = append(messages, fmt.Sprintf("%s maksimal %s karakter", e.Field(), e.Param()))
            case "oneof":
                messages = append(messages, fmt.Sprintf("%s harus salah satu dari: %s", e.Field(), e.Param()))
            default:
                messages = append(messages, fmt.Sprintf("%s tidak valid", e.Field()))
            }
        }
        return fmt.Sprintf("Validasi gagal: %v", messages)
    }
    return err.Error()
}

func (h *` + data.Name + `Handler) categorizeError(err error) (int, string) {
    if err == nil {
        return http.StatusOK, "SUCCESS"
    }

    errStr := err.Error()
    
    if h.isTimeoutError(err) {
        return http.StatusRequestTimeout, "REQUEST_TIMEOUT"
    }
    
    if h.isNetworkError(err) {
        return http.StatusBadGateway, "NETWORK_ERROR"
    }
    
    if h.isAuthError(errStr) {
        return http.StatusUnauthorized, "AUTH_ERROR"
    }
    
    return http.StatusInternalServerError, "INTERNAL_ERROR"
}

func (h *` + data.Name + `Handler) mapBpjsCodeToHttpStatus(bpjsCode string) int {
    switch bpjsCode {
    case "200":
        return http.StatusOK
    case "201":
        return http.StatusNotFound
    case "202":
        return http.StatusBadRequest
    case "400":
        return http.StatusBadRequest
    case "401":
        return http.StatusUnauthorized
    case "403":
        return http.StatusForbidden
    case "404":
        return http.StatusNotFound
    case "500":
        return http.StatusInternalServerError
    default:
        return http.StatusUnprocessableEntity
    }
}

func (h *` + data.Name + `Handler) isTimeoutError(err error) bool {
    return err != nil && (err.Error() == "context deadline exceeded" || 
        err.Error() == "timeout")
}

func (h *` + data.Name + `Handler) isNetworkError(err error) bool {
    return err != nil && (err.Error() == "connection refused" || 
        err.Error() == "no such host")
}

func (h *` + data.Name + `Handler) isAuthError(errStr string) bool {
    return errStr == "unauthorized" || errStr == "invalid credentials"
}`
}

// ================= OPTIMIZED MODEL GENERATION =====================

func generateOptimizedBpjsModelFile(data BpjsHandlerData, modelDir string) {
	modelContent := `package models

import (
    "encoding/json"
    "fmt"
    "time"
)

// ` + data.Name + ` BPJS Models with Enhanced Validation
// Generated at: ` + data.Timestamp + `
// Category: ` + data.Category + `

// Base request/response structures
type BaseRequest struct {
    RequestID string    ` + "`json:\"request_id,omitempty\"`" + `
    Timestamp time.Time ` + "`json:\"timestamp,omitempty\"`" + `
}

type BaseResponse struct {
    Status    string            ` + "`json:\"status\"`" + `
    Message   string            ` + "`json:\"message\"`" + `
    Data      interface{}       ` + "`json:\"data,omitempty\"`" + `
    Error     *ErrorResponse    ` + "`json:\"error,omitempty\"`" + `
    Metadata  *ResponseMetadata ` + "`json:\"metadata,omitempty\"`" + `
}

type ErrorResponse struct {
    Code    string ` + "`json:\"code\"`" + `
    Message string ` + "`json:\"message\"`" + `
    Details string ` + "`json:\"details,omitempty\"`" + `
}

type ResponseMetadata struct {
    Timestamp time.Time ` + "`json:\"timestamp\"`" + `
    Version   string    ` + "`json:\"version\"`" + `
    RequestID string    ` + "`json:\"request_id,omitempty\"`" + `
}

// ` + data.Name + ` Response Structure
type ` + data.Name + `Response struct {
    BaseResponse
}

// BPJS Raw Response Structure
type BpjsRawResponse struct {
    MetaData struct {
        Code    string ` + "`json:\"code\"`" + `
        Message string ` + "`json:\"message\"`" + `
    } ` + "`json:\"metaData\"`" + `
    Response interface{} ` + "`json:\"response\"`" + `
}`

	if data.HasPost {
		modelContent += `

// ` + data.Name + ` POST Request Structure with Enhanced Validation
type ` + data.Name + `PostRequest struct {
    BaseRequest
    T` + data.Name + ` ` + data.Name + `Post ` + "`json:\"tsep\" binding:\"required\" validate:\"required\"`" + `
}

type ` + data.Name + `Post struct {
    // Core BPJS fields - customize based on your specific requirements
    NoKartu       string ` + "`json:\"noKartu\" binding:\"required\" validate:\"required,min=13,max=13\"`" + `
    TglLayanan    string ` + "`json:\"tglLayanan\" binding:\"required\" validate:\"required\"`" + `
    JnsPelayanan  string ` + "`json:\"jnsPelayanan\" binding:\"required\" validate:\"required,oneof=1 2\"`" + `
    PpkPelayanan  string ` + "`json:\"ppkPelayanan\" binding:\"required\" validate:\"required\"`" + `
    Catatan       string ` + "`json:\"catatan\" validate:\"omitempty,max=200\"`" + `
    User          string ` + "`json:\"user\" binding:\"required\" validate:\"required\"`" + `
}

// Validate validates the ` + data.Name + `PostRequest
func (r *` + data.Name + `PostRequest) Validate() error {
    if r.T` + data.Name + `.NoKartu == "" {
        return fmt.Errorf("nomor kartu tidak boleh kosong")
    }
    
    if len(r.T` + data.Name + `.NoKartu) != 13 {
        return fmt.Errorf("nomor kartu harus 13 digit")
    }
    
    if _, err := time.Parse("2006-01-02", r.T` + data.Name + `.TglLayanan); err != nil {
        return fmt.Errorf("format tanggal layanan tidak valid, gunakan yyyy-MM-dd")
    }
    
    return nil
}

// ToJSON converts struct to JSON string
func (r *` + data.Name + `PostRequest) ToJSON() (string, error) {
    data, err := json.Marshal(r)
    return string(data), err
}`
	}

	if data.HasPut {
		modelContent += `

// ` + data.Name + ` PUT Request Structure with Enhanced Validation
type ` + data.Name + `PutRequest struct {
    BaseRequest
    T` + data.Name + ` ` + data.Name + `Put ` + "`json:\"tsep\" binding:\"required\" validate:\"required\"`" + `
}

type ` + data.Name + `Put struct {
    ID            string ` + "`json:\"id\" binding:\"required\" validate:\"required\"`" + `
    NoKartu       string ` + "`json:\"noKartu\" validate:\"omitempty,min=13,max=13\"`" + `
    TglLayanan    string ` + "`json:\"tglLayanan\" validate:\"omitempty\"`" + `
    JnsPelayanan  string ` + "`json:\"jnsPelayanan\" validate:\"omitempty,oneof=1 2\"`" + `
    PpkPelayanan  string ` + "`json:\"ppkPelayanan\" validate:\"omitempty\"`" + `
    Catatan       string ` + "`json:\"catatan\" validate:\"omitempty,max=200\"`" + `
    User          string ` + "`json:\"user\" binding:\"required\" validate:\"required\"`" + `
}

// Validate validates the ` + data.Name + `PutRequest
func (r *` + data.Name + `PutRequest) Validate() error {
    if r.T` + data.Name + `.ID == "" {
        return fmt.Errorf("ID tidak boleh kosong")
    }
    
    if r.T` + data.Name + `.NoKartu != "" && len(r.T` + data.Name + `.NoKartu) != 13 {
        return fmt.Errorf("nomor kartu harus 13 digit")
    }
    
    return nil
}

// ToJSON converts struct to JSON string
func (r *` + data.Name + `PutRequest) ToJSON() (string, error) {
    data, err := json.Marshal(r)
    return string(data), err
}`
	}

	if data.HasDelete {
		modelContent += `

// ` + data.Name + ` DELETE Request Structure with Enhanced Validation
type ` + data.Name + `DeleteRequest struct {
    BaseRequest
    T` + data.Name + ` ` + data.Name + `DeleteData ` + "`json:\"tsep\" binding:\"required\" validate:\"required\"`" + `
}

type ` + data.Name + `DeleteData struct {
    ID   string ` + "`json:\"id\" binding:\"required\" validate:\"required\"`" + `
    User string ` + "`json:\"user\" binding:\"required\" validate:\"required\"`" + `
}

// Validate validates the ` + data.Name + `DeleteRequest
func (r *` + data.Name + `DeleteRequest) Validate() error {
    if r.T` + data.Name + `.ID == "" {
        return fmt.Errorf("ID tidak boleh kosong")
    }
    
    if r.T` + data.Name + `.User == "" {
        return fmt.Errorf("User tidak boleh kosong")
    }
    
    return nil
}

// ToJSON converts struct to JSON string
func (r *` + data.Name + `DeleteRequest) ToJSON() (string, error) {
    data, err := json.Marshal(r)
    return string(data), err
}`
	}

	// Add common helper structures
	modelContent += `

// Common Helper Structures for BPJS
type Flag struct {
    Flag string ` + "`json:\"flag\" binding:\"required\" validate:\"required,oneof=0 1\"`" + `
}

type Poli struct {
    Tujuan    string ` + "`json:\"tujuan\" binding:\"required\" validate:\"required\"`" + `
    Eksekutif string ` + "`json:\"eksekutif\" binding:\"required\" validate:\"required,oneof=0 1\"`" + `
}

type KlsRawat struct {
    KlsRawatHak     string ` + "`json:\"klsRawatHak\" binding:\"required\" validate:\"required,oneof=1 2 3\"`" + `
    KlsRawatNaik    string ` + "`json:\"klsRawatNaik\" validate:\"omitempty,oneof=1 2 3 4 5 6 7\"`" + `
    Pembiayaan      string ` + "`json:\"pembiayaan\" validate:\"omitempty,oneof=1 2 3\"`" + `
    PenanggungJawab string ` + "`json:\"penanggungJawab\" validate:\"omitempty,max=100\"`" + `
}

// Validation helper functions
func IsValidStatus(status string) bool {
    validStatuses := []string{"active", "inactive", "pending", "processed"}
    for _, v := range validStatuses {
        if v == status {
            return true
        }
    }
    return false
}

func IsValidJnsPelayanan(jns string) bool {
    return jns == "1" || jns == "2" // 1: rawat jalan, 2: rawat inap
}

func IsValidKlsRawat(kls string) bool {
    validKelas := []string{"1", "2", "3"}
    for _, v := range validKelas {
        if v == kls {
            return true
        }
    }
    return false
}`

	writeFile(filepath.Join(modelDir, data.NameLower+".go"), modelContent)
}

// ================= OPTIMIZED ROUTES GENERATION =====================

func updateOptimizedBpjsRoutesFile(data BpjsHandlerData) {
	routesFile := "internal/routes/v1/routes.go"
	content, err := os.ReadFile(routesFile)
	if err != nil {
		fmt.Printf("⚠️ Could not read routes.go: %v\n", err)
		fmt.Printf("📝 Please manually add these optimized routes to your routes.go file:\n")
		printOptimizedBpjsRoutesSample(data)
		return
	}

	routesContent := string(content)

	var importPath, importAlias string
	if data.Category != "" {
		importPath = fmt.Sprintf("%s/internal/handlers/%s", data.ModuleName, data.Category)
		importAlias = data.NameLower + "Handlers"
	} else {
		importPath = fmt.Sprintf("%s/internal/handlers", data.ModuleName)
		importAlias = data.NameLower + "Handlers"
	}

	// Check and add import
	importPattern := fmt.Sprintf("%s \"%s\"", importAlias, importPath)
	if !strings.Contains(routesContent, importPattern) {
		importToAdd := fmt.Sprintf("\t%s \"%s\"", importAlias, importPath)
		if strings.Contains(routesContent, "import (") {
			routesContent = strings.Replace(routesContent, "import (",
				"import (\n"+importToAdd, 1)
		}
	}

	// Build optimized routes
	newRoutes := fmt.Sprintf("\t\t// Optimized %s endpoints with enhanced error handling\n", data.Name)
	if data.Category != "" {
		newRoutes = fmt.Sprintf("\t\t// Optimized %s %s endpoints with enhanced error handling\n", data.Category, data.Name)
	}

	newRoutes += fmt.Sprintf("\t\t%sHandlerConfig := &%s.%sHandlerConfig{\n", data.NameLower, importAlias, data.Name)
	newRoutes += fmt.Sprintf("\t\t\tBpjsConfig: &config.LoadConfig().Bpjs,\n")
	newRoutes += fmt.Sprintf("\t\t\tLogger:     logger.GetLogger(),\n")
	newRoutes += fmt.Sprintf("\t\t\tValidator:  validator.New(),\n")
	newRoutes += fmt.Sprintf("\t\t}\n")
	newRoutes += fmt.Sprintf("\t\t%sHandler := %s.New%sHandler(%sHandlerConfig)\n",
		data.NameLower, importAlias, data.Name, data.NameLower)

	var routePath string
	if data.Category != "" {
		routePath = data.Category + "/" + data.NameLower
	} else {
		routePath = data.NameLower
	}

	if data.HasGet {
		newRoutes += fmt.Sprintf("\t\tv1.GET(\"/%s/:id\", %sHandler.Get%s)\n",
			routePath, data.NameLower, data.Name)
	}

	if data.HasPost {
		newRoutes += fmt.Sprintf("\t\tv1.POST(\"/%s\", %sHandler.Create%s)\n",
			routePath, data.NameLower, data.Name)
	}

	if data.HasPut {
		newRoutes += fmt.Sprintf("\t\tv1.PUT(\"/%s\", %sHandler.Update%s)\n",
			routePath, data.NameLower, data.Name)
	}

	if data.HasDelete {
		newRoutes += fmt.Sprintf("\t\tv1.DELETE(\"/%s/:id\", %sHandler.Delete%s)\n",
			routePath, data.NameLower, data.Name)
	}

	newRoutes += "\n"

	// Insert routes
	insertMarker := "\t\tprotected := v1.Group(\"/\")"
	if strings.Contains(routesContent, insertMarker) {
		if !strings.Contains(routesContent, fmt.Sprintf("New%sHandler", data.Name)) {
			routesContent = strings.Replace(routesContent, insertMarker,
				newRoutes+insertMarker, 1)
		} else {
			fmt.Printf("✅ Optimized routes for %s already exist, skipping...\n", data.Name)
			return
		}
	}

	if err := os.WriteFile(routesFile, []byte(routesContent), 0644); err != nil {
		fmt.Printf("Error writing routes.go: %v\n", err)
		return
	}

	if data.Category != "" {
		fmt.Printf("✅ Updated routes.go with optimized %s %s endpoints\n", data.Category, data.Name)
	} else {
		fmt.Printf("✅ Updated routes.go with optimized %s endpoints\n", data.Name)
	}
}

func printOptimizedBpjsRoutesSample(data BpjsHandlerData) {
	var importAlias string
	if data.Category != "" {
		importAlias = data.NameLower + "Handlers"
	} else {
		importAlias = data.NameLower + "Handlers"
	}

	var routePath string
	if data.Category != "" {
		routePath = data.Category + "/" + data.NameLower
	} else {
		routePath = data.NameLower
	}

	if data.Category != "" {
		fmt.Printf(`
// Optimized %s %s endpoints with enhanced error handling
%sHandlerConfig := &%s.%sHandlerConfig{
    BpjsConfig: &config.LoadConfig().Bpjs,
    Logger:     logger.GetLogger(),
    Validator:  validator.New(),
}
%sHandler := %s.New%sHandler(%sHandlerConfig)
`, data.Category, data.Name, data.NameLower, importAlias, data.Name, data.NameLower, importAlias, data.Name, data.NameLower)
	} else {
		fmt.Printf(`
// Optimized %s endpoints with enhanced error handling
%sHandlerConfig := &%s.%sHandlerConfig{
    BpjsConfig: &config.LoadConfig().Bpjs,
    Logger:     logger.GetLogger(),
    Validator:  validator.New(),
}
%sHandler := %s.New%sHandler(%sHandlerConfig)
`, data.Name, data.NameLower, importAlias, data.Name, data.NameLower, importAlias, data.Name, data.NameLower)
	}

	if data.HasGet {
		fmt.Printf("\tv1.GET(\"/%s/:id\", %sHandler.Get%s)\n", routePath, data.NameLower, data.Name)
	}
	if data.HasPost {
		fmt.Printf("\tv1.POST(\"/%s\", %sHandler.Create%s)\n", routePath, data.NameLower, data.Name)
	}
	if data.HasPut {
		fmt.Printf("\tv1.PUT(\"/%s\", %sHandler.Update%s)\n", routePath, data.NameLower, data.Name)
	}
	if data.HasDelete {
		fmt.Printf("\tv1.DELETE(\"/%s/:id\", %sHandler.Delete%s)\n", routePath, data.NameLower, data.Name)
	}

	fmt.Println()
}

// ================= UTILITY FUNCTIONS =====================

func writeFile(filename, content string) {
	if err := os.WriteFile(filename, []byte(content), 0644); err != nil {
		fmt.Printf("❌ Error creating file %s: %v\n", filename, err)
		return
	}

	fmt.Printf("✅ Generated optimized file: %s\n", filename)
}
