package response

import (
	"github.com/gin-gonic/gin"
)

// Response represents a standard API response
type Response struct {
	Status  string      `json:"status"`
	Message string      `json:"message,omitempty"`
	Data    interface{} `json:"data,omitempty"`
	Error   interface{} `json:"error,omitempty"`
	Meta    interface{} `json:"meta,omitempty"`
}

// Success sends a success response
func Success(c *gin.Context, statusCode int, message string, data interface{}) {
	c.JSON(statusCode, Response{
		Status:  "success",
		Message: message,
		Data:    data,
	})
}

// Error sends an error response
func Error(c *gin.Context, statusCode int, message string, err interface{}) {
	// Handle jika tipe yang dikirim adalah native error Go agar tidak menjadi objek kosong '{}' di JSON
	if e, ok := err.(error); ok {
		err = e.Error()
	}

	c.JSON(statusCode, Response{
		Status:  "error",
		Message: message,
		Error:   err,
	})
}

// ErrorWithLog mengirimkan respons error HTTP sekaligus menyisipkan error asli
// ke dalam context Gin agar bisa direkam oleh LoggingMiddleware.
func ErrorWithLog(c *gin.Context, err error, statusCode int, message string, details interface{}) {
	if err != nil {
		c.Error(err) // Meneruskan error asli ke Gin Context untuk dicatat logger
	}
	Error(c, statusCode, message, details) // Panggil fungsi Error() standar
}

// Meta contains pagination metadata
type Meta struct {
	Page       int `json:"page"`
	Limit      int `json:"limit"`
	Total      int `json:"total"`
	TotalPages int `json:"total_pages"`
}

// Paginated sends a paginated response
func Paginated(c *gin.Context, statusCode int, message string, data interface{}, meta Meta) {
	c.JSON(statusCode, Response{
		Status:  "success",
		Message: message,
		Data:    data,
		Meta:    meta,
	})
}

// =========================================================================
// BPJS FORMATTER
// =========================================================================

// BPJSMetaData merepresentasikan metadata standar dari API BPJS
type BPJSMetaData struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

// BPJSResponse merepresentasikan standar response API BPJS
type BPJSResponse struct {
	MetaData BPJSMetaData `json:"metaData"`
	Response interface{}  `json:"response,omitempty"`
}

// BPJS mengirimkan respons dengan format standar API BPJS
func BPJS(c *gin.Context, httpStatusCode int, bpjsCode string, message string, data interface{}) {
	c.JSON(httpStatusCode, BPJSResponse{
		MetaData: BPJSMetaData{
			Code:    bpjsCode, // Contoh: "200" (sukses), "201" (dibuat), atau kode error BPJS lainnya
			Message: message,
		},
		Response: data,
	})
}

// =========================================================================
// SATU SEHAT (HL7 FHIR) FORMATTER
// =========================================================================

// FHIROperationOutcome merepresentasikan struktur error standar HL7 FHIR
type FHIROperationOutcome struct {
	ResourceType string           `json:"resourceType"` // Harus selalu "OperationOutcome"
	Issue        []FHIRErrorIssue `json:"issue"`
}

// FHIRErrorIssue berisi detail issue untuk error Satu Sehat
type FHIRErrorIssue struct {
	Severity    string `json:"severity"`    // fatal | error | warning | information
	Code        string `json:"code"`        // invalid | security | exception | not-found | dll
	Diagnostics string `json:"diagnostics"` // Pesan detail / human-readable
}

// FHIR mengirimkan respons untuk resource FHIR secara langsung (standar Satu Sehat)
// Satu Sehat tidak menggunakan wrapper "data" atau "status", melainkan me-return object Resource langsung
func FHIR(c *gin.Context, statusCode int, resource interface{}) {
	c.JSON(statusCode, resource)
}

// FHIRError mengirimkan pesan error yang comply dengan format OperationOutcome FHIR
func FHIRError(c *gin.Context, statusCode int, severity, code, diagnostics string) {
	c.JSON(statusCode, FHIROperationOutcome{
		ResourceType: "OperationOutcome",
		Issue: []FHIRErrorIssue{
			{
				Severity:    severity,
				Code:        code,
				Diagnostics: diagnostics,
			},
		},
	})
}
