package controllers

import (
	"daemonService/internal/models"
	"daemonService/internal/models/obtencionCodigos/response"
	"daemonService/internal/models/sincronizacionDatos/bodyGeneric"
	"encoding/json"
	"errors"
	"net/http"
)

func RespondWithJSON[T any](w http.ResponseWriter, statusCode int, payload bodyGeneric.CustomResponse[T]) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)

	if err := json.NewEncoder(w).Encode(payload); err != nil {
		http.Error(w, "Error encoding JSON response", http.StatusInternalServerError)
	}
}

func RespondWithJSONDEMO(w http.ResponseWriter, statusCode int, payload interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)

	if err := json.NewEncoder(w).Encode(payload); err != nil {
		http.Error(w, "Error encoding JSON response", http.StatusInternalServerError)
	}
}

func RespondWithError(w http.ResponseWriter, statusCode int, errMsg string) {
	RespondWithJSON(w, statusCode, bodyGeneric.CustomResponse[any]{
		Success: false,
		Status:  statusCode,
		Message: errMsg,
		Data:    nil,
	})
}

func RespondWithSuccess(w http.ResponseWriter, statusCode int, message string, data interface{}) {

	////df := data.(models.APIResponse)
	////
	////println(datas)
	//
	//// Ejemplo: si data viene como []Moneda
	//if monedas, ok := data.(models.APIResponse); ok {
	//	//primera := monedas[0]
	//	fmt.Printf("Primera moneda: %+v\n", monedas)
	//} else {
	//	// Quizá data es []interface{} (lo típico tras un Unmarshal genérico)
	//	if arr, ok2 := data.([]interface{}); ok2 {
	//		// arr[0] es un interface{} que suele ser un map[string]interface{}
	//		if m0, ok3 := arr[0].(map[string]interface{}); ok3 {
	//			fmt.Println("Código:", m0["codigo"])
	//			fmt.Println("Descripción:", m0["descripcion"])
	//		}
	//	} else {
	//		// Tipo inesperado
	//		http.Error(w, "tipo de dato no soportado en RespondWithSuccess", 500)
	//		return
	//	}
	//}
	//
	//RespondWithJSONDEMO(w, statusCode, data)

	RespondWithJSON(w, statusCode, bodyGeneric.CustomResponse[any]{
		Success: true,
		Status:  statusCode,
		Message: message,
		Data:    data,
	})
}

// nuevo repsonse --------------------------------------------------------------------------------------------
func RespondWithJSONDemo(w http.ResponseWriter, statusCode int, payload models.APIResponseCuis) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)

	if err := json.NewEncoder(w).Encode(payload); err != nil {
		http.Error(w, "Error encoding JSON response", http.StatusInternalServerError)
	}
}

// ConvertToCuisMinimal convierte diferentes tipos de datos a CuisMinimal
func ConvertToCuisStruct(data interface{}) (models.CuisMinimal, error) {
	var cuisMinimal models.CuisMinimal

	switch typedData := data.(type) {
	case response.SoapBodyCuis:
		cuisMinimal = models.CuisMinimal{
			Codigo:        typedData.Response.Respuesta.Codigo,
			FechaVigencia: typedData.Response.Respuesta.FechaVigencia,
			Transaccion:   typedData.Response.Respuesta.Transaccion,
		}
	case models.CuisMinimal:
		cuisMinimal = typedData
	default:
		return models.CuisMinimal{}, data.(error)
		//return CuisMinimal{}, fmt.Errorf("tipo de datos incompatible")
	}
	return cuisMinimal, nil
}

// responde con éxito usando datos de tipo CuisMinimal
func RespondCuisWithSuccess(w http.ResponseWriter, statusCode int, message string, data interface{}) {

	cuisMinimal, err := ConvertToCuisStruct(data)
	if err != nil {
		var apiErr models.ApiErrorCustom
		if errors.As(err.(error), &apiErr) {
			RespondWithError(w, apiErr.Status, apiErr.Message)
			return
		} else {
			RespondWithError(w, http.StatusInternalServerError, err.Error())
			return
		}
	}

	RespondWithJSONDemo(w, statusCode, models.APIResponseCuis{
		Success: true,
		Message: message,
		Data:    cuisMinimal,
	})
}
