package controllers

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"nearle/db"
	"nearle/domain"
	"nearle/models"
	"nearle/utils"
	"net/http"
	"net/url"
	"time"

	// "os"
	"strconv"

	"github.com/gofiber/fiber/v2"
	"github.com/redis/go-redis/v9"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

func GetApplocations(c *fiber.Ctx) error {

	aid, _ := strconv.Atoi(c.Query("applocationid"))

	result := domain.GetApplocations(aid)
	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Successful",
		"details": result,
	})

}

func GetApplocationsv2(c *fiber.Ctx) error {

	userid, _ := strconv.Atoi(c.Query("userid"))

	result := domain.GetApplocationsv2(userid)

	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Successful",
		"details": result,
	})
}

func GetApplocationConfig(c *fiber.Ctx) error {

	aid, _ := strconv.Atoi(c.Query("applocationid"))

	result := domain.GetApplocationConfig(aid)
	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Successful",
		"details": result,
	})

}

func GetApplocationadmins(c *fiber.Ctx) error {

	aid, _ := strconv.Atoi(c.Query("applocationid"))

	result := domain.GetApplocationadmins(aid)

	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Successful",
		"details": result,
	})
}

func GetAppPricing(c *fiber.Ctx) error {

	aid, _ := strconv.Atoi(c.Query("applocationid"))
	cid, _ := strconv.Atoi(c.Query("configid"))
	pid, _ := strconv.Atoi(c.Query("pricingtypeid"))

	result := domain.GetAppPricing(aid, cid, pid)
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})

}

func GetAllAppPricing(c *fiber.Ctx) error {

	aid, _ := strconv.Atoi(c.Query("applocationid"))

	result := domain.GetAllAppPricing(aid)
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})

}

func CreateAppPricing(c *fiber.Ctx) error {

	var data models.Apppricing

	if err := c.BodyParser(&data); err != nil {
		return err
	}

	result := domain.CreateAppProcing(data)
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})

}

func GetAppConfig(c *fiber.Ctx) error {

	cid, _ := strconv.Atoi(c.Query("configid"))

	result := domain.GetAppconfig(cid)
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})

}
func GetAllAppConfig(c *fiber.Ctx) error {

	result := domain.GetAllAppconfig()
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})

}

func GetApptypes(c *fiber.Ctx) error {

	tag := c.Query("tag")

	result := domain.GetApptypes(tag)
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})

}

func GetSubcategories(c *fiber.Ctx) error {
	mid, _ := strconv.Atoi(c.Query("moduleid"))   // 0 means all modules
	cid, _ := strconv.Atoi(c.Query("categoryid")) // 0 means all categories

	result := domain.GetSubcategories(mid, cid)

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})
}

func GetCategories(c *fiber.Ctx) error {
	mid, _ := strconv.Atoi(c.Query("moduleid", "0")) // default to 0

	result := domain.GetCategories(mid)

	// Ensure result is never null
	if result == nil {
		result = []models.AppCategory{}
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})
}

const (
	fcmURL     = "https://fcm.googleapis.com/v1/projects/nearle-gear/messages:send"
	scope      = "https://www.googleapis.com/auth/firebase.messaging"
	serviceAcc = "nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json" // Path to your service account JSON
)

var client *http.Client

// Structure of FCM message

// GetClientFromServiceAccount reads the service account JSON file and generates a new token
func GetClientFromServiceAccount() (*http.Client, error) {
	data, err := ioutil.ReadFile(serviceAcc)
	if err != nil {
		return nil, fmt.Errorf("failed to read service account file: %v", err)
	}

	config, err := google.JWTConfigFromJSON(data, scope)
	if err != nil {
		return nil, fmt.Errorf("failed to parse service account JSON: %v", err)
	}

	// Use the token source to generate an HTTP client that automatically refreshes the token
	client := config.Client(oauth2.NoContext)
	return client, nil
}

func sendFCMMessage(token, title, body string) error {
	if client == nil {
		var err error
		client, err = GetClientFromServiceAccount()
		if err != nil {
			return fmt.Errorf("failed to get client: %v", err)
		}
	}

	notification := Notification{
		Title: title,
		Body:  body,
	}

	fcmRequest := FCMRequestBody{}
	fcmRequest.Message.Notification = notification
	fcmRequest.Message.Token = token

	requestBody, err := json.Marshal(fcmRequest)
	if err != nil {
		return err
	}

	req, err := http.NewRequest("POST", fcmURL, bytes.NewBuffer(requestBody))
	if err != nil {
		return err
	}

	req.Header.Set("Content-Type", "application/json")

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		bodyBytes, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("failed to send message: %s", string(bodyBytes))
	}

	return nil
}

func NotifyAdmin(c *fiber.Ctx) error {
	body := new(struct {
		Token        []string `json:"token"`
		Notification struct {
			Title string `json:"title"`
			Body  string `json:"body"`
			Sound string `json:"sound"`
			Type  string `json:"type"`
		} `json:"notification"`
	})

	if err := c.BodyParser(body); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
	}

	if len(body.Token) == 0 {
		return fiber.NewError(fiber.StatusBadRequest, "No tokens provided")
	}

	// Only send FCM to provided tokens
	var successCount, failureCount int
	for _, token := range body.Token {
		err := sendFCMMessage(token, body.Notification.Title, body.Notification.Body)

		if err != nil {
			utils.Logger.Errorf("❌ Failed to send to %s: %v", token, err)
			failureCount++
		} else {
			utils.Logger.Infof("✅ Notification sent to %s", token)
			successCount++
		}
	}

	return c.Status(fiber.StatusOK).JSON(fiber.Map{
		"message": "Admin notifications sent",
		"success": successCount,
		"failure": failureCount,
	})
}

func NotifyTenant(c *fiber.Ctx) error {

	body := new(struct {
		Token        []string `json:"token"`
		TenantID     int      `json:"tenantid"`
		ModuleID     int      `json:"moduleid"`
		LocationID   int      `json:"locationid"`
		CustomerID   int      `json:"customerid"`
		Notification struct {
			Title string `json:"title"`
			Body  string `json:"body"`
			Sound string `json:"sound"`
			Type  string `json:"type"`
		} `json:"notification"`
	})

	if err := c.BodyParser(body); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
	}

	if len(body.Token) == 0 {
		return fiber.NewError(fiber.StatusBadRequest, "No tokens provided")
	}

	successCount := 0
	failureCount := 0

	// Loop through each token and send notification + insert DB log
	for _, token := range body.Token {

		err := sendFCMMessage(token, body.Notification.Title, body.Notification.Body)

		successCode := 0
		if err != nil {
			utils.Logger.Errorf("❌ Failed to send to %s: %v", token, err)
			failureCount++
		} else {
			utils.Logger.Infof("✅ Notification sent to %s", token)
			successCount++
			successCode = 1
		}

		// Insert into tenantnotifications table
		insertQuery := `
			INSERT INTO tenantnotifications
			(title, message, tenantid, moduleid, locationid, customerid, notificationdate, successcode)
			VALUES (?, ?, ?, ?, ?, ?, NOW(), ?)
		`

		if dbErr := db.DB.Exec(
			insertQuery,
			body.Notification.Title,
			body.Notification.Body,
			body.TenantID,
			body.ModuleID,
			body.LocationID,
			body.CustomerID,
			successCode,
		).Error; dbErr != nil {
			utils.Logger.Errorf("❌ DB Insert Error: %v", dbErr)
		}
	}

	return c.Status(fiber.StatusOK).JSON(fiber.Map{
		"message": "Tenant notifications processed",
		"success": successCount,
		"failure": failureCount,
	})
}

func GetTenantNotifications(c *fiber.Ctx) error {
	tenantid, _ := strconv.Atoi(c.Query("tenantid"))
	locationid, _ := strconv.Atoi(c.Query("locationid"))
	customerid, _ := strconv.Atoi(c.Query("customerid"))
	moduleid, _ := strconv.Atoi(c.Query("moduleid"))

	pageno, _ := strconv.Atoi(c.Query("pageno"))
	pagesize, _ := strconv.Atoi(c.Query("pagesize"))

	if pageno == 0 {
		pageno = 1
	}
	if pagesize == 0 {
		pagesize = 10
	}

	result, _ := domain.GetTenantNotifications(
		tenantid, locationid, customerid, moduleid,
		pageno, pagesize,
	)

	return c.JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Successful",
		"details": result,
	})
}

type Notification struct {
	Title string `json:"title"`
	Body  string `json:"body"`
}

type FCMRequestBody struct {
	Message struct {
		Notification Notification `json:"notification"`
		Token        string       `json:"token"`
	} `json:"message"`
}

type WebhookPayload struct {
	ID             string      `json:"id"`
	Event          string      `json:"event"`
	Timestamp      string      `json:"timestamp"`
	Vendor         string      `json:"vendor"`
	FailedAttempts int         `json:"failedAttempts"`
	WebhookID      string      `json:"webhookId"`
	Payload        interface{} `json:"payload"`
	Context        interface{} `json:"context"`
}

func WebhookHandler(c *fiber.Ctx) error {
	utils.Info("➡️ Incoming webhook request")

	var webhook WebhookPayload
	if err := c.BodyParser(&webhook); err != nil {
		utils.Logger.Errorf("❌ Failed to parse webhook JSON: %v", err)
		utils.Logger.Errorf("Request body: %s", string(c.Body()))
		return c.Status(fiber.StatusBadRequest).SendString("Invalid JSON")
	}

	utils.Logger.Infof("✅ Received event: %s at %s", webhook.Event, webhook.Timestamp)
	utils.Logger.Infof("🧾 Payload: %+v", webhook.Payload)

	return c.SendStatus(fiber.StatusOK)
}

func RegisterWebhookHandler(c *fiber.Ctx) error {
	// Shopfront GraphQL API endpoint
	url := "https://testshopfront.onshopfront.com/api/v2/graphql"

	// Webhook registration mutation
	payload := map[string]string{
		"query": `
mutation {
  registerWebhook(input: {
    name: "Sale Webhook",
    url: "https://jupiter.nearle.app/live/api/v1/utils/webhooks",
    events: [sale_created]
  }) {
    id
    name
    url
    events
    active
  }
}`,
	}

	// Marshal payload
	body, _ := json.Marshal(payload)

	// Create POST request
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzODUiLCJqdGkiOiI2OTA5MmM3ZmY0YzgzNmExNTBmZWIyOGU3N2RkOWYzMDFjNjM4ZGQ5ODViOGExZjMzYjdhODY1MzFhMzQxNjM0NTQ2ZjMxMTY0M2JjMGUzNSIsImlhdCI6MTc1MzExMTY5NC44OTAyNjksIm5iZiI6MTc1MzExMTY5NC44OTAyNzQsImV4cCI6MTc1NDMyMTI5NC44Nzg2OTYsInN1YiI6IiIsInNjb3BlcyI6WyJjcmVhdGVfd2ViaG9va3MiXX0.WtE2eYES3MWdcvQZIu0AubIzUAv839-c_UoSUdCx5ez2Px03u-YZbCX114LxAhcLIZbQBiyaFB24pW3ojQf_RIdIvDnWPoMo7RWDDVYiHT9xHbe6Crht4ORkaYF2IOijXCYgDRgXT3whBNVldFhFAyfhcj9qVehJdmpRh5QGmt0PT9LWoy7XeFR_ksmOPjufvv1JZLITYilT7SijrkpSvDsqUBlCXj86ifIFY9q3A2zexb7GlSvdE_RmRegPr0kLA23i4J4uwo9BBPDaJaIGYIP4C6x5j9fYBOmf0v3cSt1teoVGBFedjrizH4qvWazDZl44OlwlE6QQYCXpmjgFWXtLeiI54JQ-tygCbxi7xB_O4v8oqj_G4aP-aM-PykC5ge11ekJuCJXhsLcJajgztcjVVz8Bmnh0U5nnRG9Qx0szTiuy07p6y73IN4gWfLFjRd16pryhPjAHzI5bzbRGG_Pd0M5NcT7krZkQGEDkpuNgDKni6GgLQBy4My_mskJXjTw9lYP5i2Okn9CywJ5qaPNRMWW8eiEpb8qwzXxS2IRQQSKnpkT88P1LcSUMBhermYq60KFuh1RKYG5jNoWo2xwCsNJygCCk4iwtAvlhBoAZiOPwYJcgSM6jPdwqoUuRys_tqs938zIuf9hTdDosm5WM9z1sxXX-nqSfLqFuN_M") // Replace with valid token

	// ✅ Add debug logs
	utils.Logger.Infof("Request body: %s", string(body))
	utils.Logger.Infof("Authorization header: %s", req.Header.Get("Authorization"))

	// Send the request
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		utils.Logger.Errorf("Failed to register webhook: %v", err)
		return c.Status(500).SendString("Webhook registration failed")
	}
	defer resp.Body.Close()

	respBody, _ := io.ReadAll(resp.Body)
	utils.Logger.Infof("Webhook registration response: %s", respBody)

	return c.Status(resp.StatusCode).SendString(string(respBody))
}

type WebhookInput struct {
	Topic       string `json:"topic"`
	DeliveryUrl string `json:"delivery_url"`
}

func Createwebhook(c *fiber.Ctx) error {
	code := c.Query("code")
	vendor := c.Query("vendor")

	// ✅ Handle OAuth callback
	if code != "" && vendor != "" {
		utils.Logger.Infof("✅ Received OAuth Code: %s", code)
		utils.Logger.Infof("✅ Vendor: %s", vendor)

		// 🔁 Exchange code for access token
		tokenResp, err := http.PostForm("https://"+vendor+".onshopfront.com/oauth/token", url.Values{
			"client_id":     []string{"kY3Dfvohj8BV4lEoUDKSEsyRGnlGpXi8"},
			"client_secret": []string{"Qk2eUXHaveIFEMNTny0yvVB1aHWvIY5J7blKwdHx"},
			"code":          []string{code},
			"grant_type":    []string{"client_credentials"},
			"redirect_uri":  []string{"https://jupiter.nearle.app/live/api/v1/utils/createwebhook"},
		})

		if err != nil {
			utils.Logger.Errorf("❌ Token exchange error: %v", err)
			return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
				"status":  false,
				"message": "Failed to exchange code for access token",
			})
		}
		defer tokenResp.Body.Close()

		var tokenData map[string]interface{}
		json.NewDecoder(tokenResp.Body).Decode(&tokenData)
		utils.Logger.Infof("🔐 Token response: %v", tokenData)

		accessToken, ok := tokenData["access_token"].(string)
		if !ok || accessToken == "" {
			return c.Status(500).JSON(fiber.Map{
				"status":  false,
				"message": "Access token missing in response",
			})
		}

		// ✅ Send accessToken back or store it (in DB, session, etc.)
		return c.JSON(fiber.Map{
			"status":       true,
			"message":      "OAuth successful",
			"access_token": accessToken,
		})
	}

	// ✅ Handle webhook registration
	var input WebhookInput
	if err := c.BodyParser(&input); err != nil {
		utils.Logger.Errorf("❌ BodyParser Error: %v", err)
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"message": "Invalid request body",
		})
	}

	if input.Topic == "" || input.DeliveryUrl == "" {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"message": "Topic and Delivery URL are required",
		})
	}

	payload := map[string]string{
		"topic":        input.Topic,
		"delivery_url": input.DeliveryUrl,
	}
	jsonPayload, _ := json.Marshal(payload)

	// ❗ Replace this with actual token from DB/session
	accessToken := "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzODUiLCJqdGkiOiIwNmI3Y2M0YTA4YzY1NDhlMmYzNTU3Nzg0MDAyNDdmMjk0ZTliOTBkMzQ4MjNjODZkNjJhNTU4NjZhZWE5M2EwNTZlYjQ4ZjM2NTQ3MTE0YyIsImlhdCI6MTc1MzM0MjczNi42MDc2NTcsIm5iZiI6MTc1MzM0MjczNi42MDc2NjIsImV4cCI6MTc1NDU1MjMzNi41OTQ3MTksInN1YiI6IiIsInNjb3BlcyI6WyJjcmVhdGVfd2ViaG9va3MiXX0.jl4ln8Qv2apX4A_uxohS2Rqj6hShBQD1M2tGV-8fkUPrxg8anh-4aDEApFiaZuB8PkfereU5nPlMP_r5Hs5vWNTIgZyp6A-uwUp89c7NZyQng9aCfmRCN0yN0VeV4SWMKasp6uFacG-_MrzToQPtsYGGam7tG8j5apfcy3spXvJSC7CwwfRxL-Kpi1mJ-t272onWZblEhLrwiMbKc_6B5mVCV8TkCsY6YS8UDT5SC93X8_l2X3wjg2MP-fL9zUWz13qK4xHVDvqpx2mc0fG-ZI7oJpafC5j8GszVkobKqQTwMACuJSt5l6AgWcau4uPKglMIzUqapipSuu4jjKvQCQQAwLaL8Xc9Zy_vtMgGepdNEcuRn7uZqg1CMHCUKqvYWu-YU_4hWlzHVUu3A4SPcs5ZfxIj5D5smMffQb_2FQm4PThMlJKD4T697VLm0jKfDN0P8c3PINhiEpixJFh-njlCCNUXylO4SxG2Q8Yg_nBMLGuTevsSZaZLXd4_Zvsw3tZpoDOGWyZ0-fjBcbCvjmq_eY2S1emdwHYNhoFo8j0FJjKuEnwj0XylaQu6bt1PF8E_LQit9SK2umVMRAtb7ayocoz9iSi6NP3416aI7B97pUwqWKzy9or7LKtydAfzfuFCzlhuXf_iW3VhQR8QlFJtUuKIt7Nfu3gGAm6pk0"

	req, err := http.NewRequest("POST", "https://testshopfront.onshopfront.com/api/v1/webhooks", bytes.NewBuffer(jsonPayload))
	if err != nil {
		utils.Logger.Errorf("❌ Failed to create request: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to create webhook request",
		})
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+accessToken)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		utils.Logger.Errorf("❌ Error calling Shopfront API: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"message": "Error sending request to Shopfront",
		})
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	utils.Logger.Infof("🔁 Shopfront Response: %s", string(body))

	return c.Status(resp.StatusCode).Send(body)
}

func WebhookReceiver(c *fiber.Ctx) error {
	var webhookData struct {
		ID             string                 `json:"id"`
		Event          string                 `json:"event"`
		Timestamp      string                 `json:"timestamp"`
		Vendor         string                 `json:"vendor"`
		FailedAttempts int                    `json:"failedAttempts"`
		WebhookID      string                 `json:"webhookId"`
		Payload        map[string]interface{} `json:"payload"`
		Context        interface{}            `json:"context"`
	}

	if err := c.BodyParser(&webhookData); err != nil {
		utils.Logger.Errorf("❌ Error parsing webhook payload: %v", err)
		return c.SendStatus(fiber.StatusBadRequest) // 400
	}

	// Log webhook info for debugging
	utils.Info("🔔 Webhook received:")
	utils.Logger.Infof("ID: %s", webhookData.ID)
	utils.Logger.Infof("Event: %s", webhookData.Event)
	utils.Logger.Infof("Timestamp: %s", webhookData.Timestamp)
	utils.Logger.Infof("Vendor: %s", webhookData.Vendor)
	utils.Logger.Infof("Payload: %v", webhookData.Payload)

	// Return 200 OK with no body
	return c.SendStatus(fiber.StatusOK)
}

func GetShopfrontOrders(c *fiber.Ctx) error {
	url := "https://testshopfront.onshopfront.com/graphql"
	accessToken := "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIzODUiLCJqdGkiOiI5NzMzZjk3ZjlmNjAxMWM4NDc4NDE3Y2JlN2MzM2VjZjM0YzJiNWUyNDMzNjBmNTliNTg3NzgzZWZkOGYxOGQ0NjQ3MjZmMjMzMzAwOTE2YSIsImlhdCI6MTc1MzQyOTE2Ni4zMzkxNiwibmJmIjoxNzUzNDI5MTY2LjMzOTE2NSwiZXhwIjoxNzU0NjM4NzY2LjMyMjUzOSwic3ViIjoiIiwic2NvcGVzIjpbIioiXX0.1ne-a29-wS_HUn3vVnuUA1ikXeXfLtz6AMktFfbj1Zc4L1ih_PJAHvzODbgErv9pR-6AucDyxH2ZlJSb7MAL-V93yDMGK672n4lxXNDcVqgZEGjCrn7WlyopLhZDhjKJMzRFn1CN4FkW2P31Jgl55W0Ff_prX13usLy_Cad8rNlnp15TaTgJed-m40hsOeWEjQDP_LJWQCHSf2wXNPx-tpRe1FEbh6QQNV4nT3TRqUQEhWvd_nQXiqnZaqY0q6Xbgq_Vn-laNNySIvtyISaoS0jxfrSF2856FBhF-WKIzMfQs1oeQioZL-2IH1QGKrbCJfV9Z4gTaGfVLV8ZAWp1XB3CmpDFgEJih_H76u1NvIXs8S343jq6klV1GKaqvuYfz8RfwtNx7mfP6mOwve3SkRSuHZOedzcgKjdETL8AWx7AT-6gbSdGX49ktqD0NbixzfBu2MGkBn6j7vMVgtNqfrYHcfZAP65gRlo9UGsKAvAFbAZnGoO-FHC3R9iSOM2llmLNg65OoaPazavOfnKhLWzk06gS3t_8HJenqTM_7tp6YsW-W57k5y5MzJYcHvXSplvG8VYUFEkRo6PeGq7cib_78IopAp3vgxODSaDa9ETkn2RHGLS8IyMK6pAP7OLpZyc6lxNgDqnZE3S2kAqdrOgvrld3NzP4hWpwA3dka8"

	query := `{
		"query": "query { orders(first: 10) { edges { node { id invoiceNumber orderDate status totalCost } } } }"
	}`

	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(query)))
	if err != nil {
		utils.Logger.Errorf("❌ Request creation failed: %v", err)
		return c.Status(500).JSON(fiber.Map{"error": "Request creation failed"})
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+accessToken)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		utils.Logger.Errorf("❌ Request failed: %v", err)
		return c.Status(500).JSON(fiber.Map{"error": "Request execution failed"})
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)

	return c.Status(resp.StatusCode).Send(body)
}

func RegisterInventoryWebhook(c *fiber.Ctx) error {
	// Log or process the incoming payload
	var payload map[string]interface{}
	if err := c.BodyParser(&payload); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": "Invalid payload",
		})
	}
	utils.Logger.Infof("📦 Inventory Webhook Received: %v", payload)

	// Always return 2xx status with no body
	return c.SendStatus(fiber.StatusNoContent) // 204
}

func GetAppModule(c *fiber.Ctx) error {

	result := domain.GetAppModule()
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": result,
	})

}

func GetUserBonusSummary(c *fiber.Ctx) error {

	userid, err := strconv.Atoi(c.Query("userid"))
	if err != nil || userid == 0 {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    400,
			"message": "Valid userid is required",
		})
	}

	data, err := domain.GetUserBonusSummary(userid)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    500,
			"message": err.Error(),
		})
	}

	return c.Status(fiber.StatusOK).JSON(fiber.Map{
		"status":  true,
		"code":    200,
		"message": "Success",
		"details": data,
	})
}

func CreateAppLocationConfig(c *fiber.Ctx) error {

	var data models.AppLocationConfigRequest

	if err := c.BodyParser(&data); err != nil {
		return err
	}

	result := domain.CreateAppLocationConfig(data)

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  result,
	})
}

func UpdateAppLocationConfig(c *fiber.Ctx) error {

	var data models.AppLocationConfigRequest

	if err := c.BodyParser(&data); err != nil {
		return err
	}

	result := domain.UpdateAppLocationConfig(data)

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  result,
	})
}

func GetUserRoles(c *fiber.Ctx) error {

	roles, err := domain.GetUserRoles()
	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"success": false,
			"message": "Failed to fetch roles",
			"error":   err.Error(),
		})
	}

	return c.JSON(fiber.Map{
		"status":  true,
		"code":    200,
		"message": "Success",
		"details": roles,
	})
}

// ============================================================================
// REDIS USER STORAGE ENDPOINTS
// ============================================================================

// StoreUserRedis - POST /api/v1/utils/users/redis
// Store user data in Redis with ZSET index and HASH storage
func CreateUserRedis(c *fiber.Ctx) error {
	ctx := context.Background()

	// Parse request body
	var userData struct {
		UserID       int    `json:"userid"`
		Username     string `json:"username"`
		FirstName    string `json:"firstname"`
		LastName     string `json:"lastname"`
		ContactNo    string `json:"contactno"`
		UserFCMToken string `json:"userfcmtoken"`
		AppVersion   string `json:"app_version"`
		DeviceInfo   string `json:"device_info"`
	}

	if err := c.BodyParser(&userData); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "Invalid request body",
		})
	}

	// Validate required fields
	if userData.UserID == 0 || userData.Username == "" || userData.FirstName == "" || userData.LastName == "" {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "userid, username, firstname, and lastname are required",
		})
	}

	// Check Redis connection
	pong, err := db.Rdb.Ping(ctx).Result()
	utils.Logger.Infof("[Redis] Ping: %s Error: %v", pong, err)
	if err != nil {
		utils.Logger.Errorf("❌ Redis connection error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Redis connection error: " + err.Error(),
		})
	}

	// Marshal user data to JSON
	jsonData, err := json.Marshal(userData)
	if err != nil {
		utils.Logger.Errorf("❌ JSON marshal error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to serialize user data",
		})
	}

	// Store in HASH: "user:{userid}"
	userKey := fmt.Sprintf("user:%d", userData.UserID)
	if err := db.Rdb.Set(ctx, userKey, jsonData, 0).Err(); err != nil {
		utils.Logger.Errorf("❌ Redis SET error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to store user in Redis",
		})
	}

	utils.Logger.Infof("✅ User stored in HASH — key=%s", userKey)

	// Add to ZSET with timestamp as score: "user" → {score: timestamp, member: userid}
	now := time.Now().Unix()
	zadd := db.Rdb.ZAdd(ctx, "user", redis.Z{
		Score:  float64(now),
		Member: fmt.Sprintf("%d", userData.UserID),
	})
	if zadd.Err() != nil {
		utils.Logger.Errorf("❌ Redis ZADD error: %v", zadd.Err())
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to index user in ZSET",
		})
	}

	utils.Logger.Infof("✅ User indexed in ZSET — key=user, member=%d, score=%d", userData.UserID, now)

	return c.Status(http.StatusCreated).JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusCreated,
		"message": "User stored successfully in Redis",
		"data":    userData,
	})
}

// GetUserRedis - GET /api/v1/utils/users/redis/:userid
// Retrieve user data from Redis by userid
func GetUserRedis(c *fiber.Ctx) error {
	ctx := context.Background()

	userIDStr := c.Query("userid")
	pageStr := c.Query("page")
	pageSizeStr := c.Query("pagesize")

	// 🔹 CASE 1: Single user
	if userIDStr != "" {
		userID, err := strconv.Atoi(userIDStr)
		if err != nil || userID == 0 {
			return c.Status(http.StatusBadRequest).JSON(fiber.Map{
				"status":  false,
				"code":    http.StatusBadRequest,
				"message": "Valid userid parameter is required",
			})
		}

		userKey := fmt.Sprintf("user:%d", userID)

		userData, err := db.Rdb.Get(ctx, userKey).Result()
		if err != nil {
			return c.Status(http.StatusNotFound).JSON(fiber.Map{
				"status":  false,
				"code":    http.StatusNotFound,
				"message": "User not found",
			})
		}

		var user map[string]interface{}
		json.Unmarshal([]byte(userData), &user)

		return c.JSON(fiber.Map{
			"status": true,
			"data":   user,
		})
	}

	// 🔹 CASE 2: ALL users with pagination

	var (
		page     int
		pageSize int
		err      error
	)

	if pageStr != "" {
		page, err = strconv.Atoi(pageStr)
		if err != nil || page <= 0 {
			return c.Status(400).JSON(fiber.Map{
				"status":  false,
				"message": "invalid page",
			})
		}
	}

	if pageSizeStr != "" {
		pageSize, err = strconv.Atoi(pageSizeStr)
		if err != nil || pageSize <= 0 {
			return c.Status(400).JSON(fiber.Map{
				"status":  false,
				"message": "invalid pagesize",
			})
		}
	}

	var start, end int64

	if page > 0 && pageSize > 0 {
		offset := (page - 1) * pageSize
		start = int64(offset)
		end = int64(offset + pageSize - 1)
	} else {
		start = 0
		end = -1 // fetch ALL
	}

	// ✅ Get user IDs from ZSET
	userIDs, err := db.Rdb.ZRevRange(ctx, "user", start, end).Result()
	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to fetch users",
		})
	}

	// Convert to keys
	var keys []string
	for _, id := range userIDs {
		keys = append(keys, fmt.Sprintf("user:%s", id))
	}

	// ✅ Use MGET (fast)
	values, err := db.Rdb.MGet(ctx, keys...).Result()
	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to fetch user data",
		})
	}

	var users []map[string]interface{}

	for _, val := range values {
		if val == nil {
			continue
		}

		var user map[string]interface{}
		json.Unmarshal([]byte(val.(string)), &user)

		users = append(users, user)
	}

	// ✅ total count (optional)
	// total, _ := db.Rdb.ZCard(ctx, "user").Result()

	return c.JSON(fiber.Map{

		"code":    http.StatusOK,
		"data":    users,
		"message": "Success",
		"status":  true,
	})
}

// UpdateUserRedis - PUT /api/v1/utils/users/redis/:userid
// Update user data in Redis
func UpdateUserRedis(c *fiber.Ctx) error {
	ctx := context.Background()

	userIDStr := c.Params("userid")
	userID, err := strconv.Atoi(userIDStr)
	if err != nil || userID == 0 {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "Valid userid parameter is required",
		})
	}

	// Parse request body
	var userData map[string]interface{}
	if err := c.BodyParser(&userData); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "Invalid request body",
		})
	}

	// Check Redis connection
	_, err = db.Rdb.Ping(ctx).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis connection error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Redis connection error",
		})
	}

	// Check if user exists
	userKey := fmt.Sprintf("user:%d", userID)
	exists, err := db.Rdb.Exists(ctx, userKey).Result()
	if err != nil || exists == 0 {
		utils.Logger.Warnf("⚠️ User not found for update — key=%s", userKey)
		return c.Status(http.StatusNotFound).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusNotFound,
			"message": "User not found",
		})
	}

	// Add userid to update data
	userData["userid"] = userID

	// Marshal updated data
	jsonData, err := json.Marshal(userData)
	if err != nil {
		utils.Logger.Errorf("❌ JSON marshal error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to serialize user data",
		})
	}

	// Update in HASH
	if err := db.Rdb.Set(ctx, userKey, jsonData, 0).Err(); err != nil {
		utils.Logger.Errorf("❌ Redis SET error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to update user in Redis",
		})
	}

	utils.Logger.Infof("✅ User updated in HASH — key=%s", userKey)

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "User updated successfully",
		"data":    userData,
	})
}

// DeleteUserRedis - DELETE /api/v1/utils/users/redis/:userid
// Delete user from both HASH and ZSET
func DeleteUserRedis(c *fiber.Ctx) error {
	ctx := context.Background()

	userIDStr := c.Params("userid")
	userID, err := strconv.Atoi(userIDStr)
	if err != nil || userID == 0 {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "Valid userid parameter is required",
		})
	}

	// Check Redis connection
	_, err = db.Rdb.Ping(ctx).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis connection error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Redis connection error",
		})
	}

	userKey := fmt.Sprintf("user:%d", userID)
	userIDStr = fmt.Sprintf("%d", userID)

	// Delete from HASH
	delResult, err := db.Rdb.Del(ctx, userKey).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis DEL error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to delete user",
		})
	}

	utils.Logger.Infof("✅ User deleted from HASH — key=%s, deleted=%d", userKey, delResult)

	// Remove from ZSET
	remResult, err := db.Rdb.ZRem(ctx, "user", userIDStr).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis ZREM error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to remove user from index",
		})
	}

	utils.Logger.Infof("✅ User removed from ZSET — key=user, member=%s, removed=%d", userIDStr, remResult)

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "User deleted successfully",
	})
}

// GetAllUsersRedis - GET /api/v1/utils/users/redis
// Retrieve all users from ZSET
func GetAllUsersRedis(c *fiber.Ctx) error {
	ctx := context.Background()

	// Check Redis connection
	_, err := db.Rdb.Ping(ctx).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis connection error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Redis connection error",
		})
	}

	// Get all user IDs from ZSET
	userIDs, err := db.Rdb.ZRange(ctx, "user", 0, -1).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis ZRANGE error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to fetch users",
		})
	}

	utils.Logger.Infof("✅ Retrieved %d user IDs from ZSET", len(userIDs))

	// Fetch each user's data
	var users []map[string]interface{}
	for _, userIDStr := range userIDs {
		userKey := fmt.Sprintf("user:%s", userIDStr)
		userData, err := db.Rdb.Get(ctx, userKey).Result()
		if err != nil {
			utils.Logger.Warnf("⚠️ Failed to get user data — key=%s", userKey)
			continue
		}

		var user map[string]interface{}
		if err := json.Unmarshal([]byte(userData), &user); err != nil {
			utils.Logger.Warnf("⚠️ Failed to unmarshal user data — key=%s", userKey)
			continue
		}

		users = append(users, user)
	}

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Success",
		"count":   len(users),
		"data":    users,
	})
}

// UserExistsRedis - GET /api/v1/utils/users/redis/:userid/exists
// Check if user exists in Redis
func UserExistsRedis(c *fiber.Ctx) error {
	ctx := context.Background()

	userIDStr := c.Params("userid")
	userID, err := strconv.Atoi(userIDStr)
	if err != nil || userID == 0 {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusBadRequest,
			"message": "Valid userid parameter is required",
		})
	}

	// Check Redis connection
	_, err = db.Rdb.Ping(ctx).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis connection error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Redis connection error",
		})
	}

	userKey := fmt.Sprintf("user:%d", userID)
	exists, err := db.Rdb.Exists(ctx, userKey).Result()
	if err != nil {
		utils.Logger.Errorf("❌ Redis EXISTS error: %v", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to check user existence",
		})
	}

	userExists := exists > 0
	utils.Logger.Infof("✅ User existence check — userid=%d, exists=%v", userID, userExists)

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Success",
		"exists":  userExists,
	})
}

func CreateRiderPeriodicLog(c *fiber.Ctx) error {
	ctx := context.Background()

	var log models.RiderLog
	if err := c.BodyParser(&log); err != nil {
		return c.Status(400).JSON(fiber.Map{
			"status":  false,
			"message": "Invalid request body",
		})
	}

	// Parse logdate
	t, err := time.Parse("2006-01-02 15:04:05", log.LogDate)
	if err != nil {
		return c.Status(400).JSON(fiber.Map{
			"status":  false,
			"message": "Invalid logdate format",
		})
	}

	timestamp := t.Unix()

	// Key
	logKey := fmt.Sprintf("rider_periodic_log:%d:%d", log.UserID, timestamp)

	data, _ := json.Marshal(log)

	// Store STRING
	err = db.Rdb.Set(ctx, logKey, data, 0).Err()
	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to store log",
		})
	}

	// ✅ Per-user ZSET
	userZsetKey := fmt.Sprintf("rider_periodic_logs:%d", log.UserID)
	err = db.Rdb.ZAdd(ctx, userZsetKey, redis.Z{
		Score:  float64(timestamp),
		Member: logKey,
	}).Err()

	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to index user log",
		})
	}

	// 🔥 ADD THIS (GLOBAL INDEX)
	err = db.Rdb.ZAdd(ctx, "rider_periodic_logs_all", redis.Z{
		Score:  float64(timestamp),
		Member: logKey,
	}).Err()

	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to index global log",
		})
	}

	return c.JSON(fiber.Map{
		"status":  true,
		"message": "Rider periodic log stored",
	})
}

func GetRiderPeriodicLogs(c *fiber.Ctx) error {
	ctx := context.Background()

	userID := c.Query("userid")

	var keys []string
	var err error

	if userID != "" {
		// ✅ USER specific (latest only)
		zsetKey := fmt.Sprintf("rider_periodic_logs:%s", userID)
		keys, err = db.Rdb.ZRevRange(ctx, zsetKey, 0, 0).Result()
	} else {
		// ✅ GLOBAL (latest only)
		keys, err = db.Rdb.ZRevRange(ctx, "rider_periodic_logs_all", 0, 0).Result()
	}

	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to fetch logs",
		})
	}

	if len(keys) == 0 {
		return c.JSON(fiber.Map{
			"code":    200,
			"data":    []interface{}{},
			"message": "No logs found",
			"status":  true,
		})
	}

	// 🔥 Get only one value
	val, err := db.Rdb.Get(ctx, keys[0]).Result()
	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to fetch log data",
		})
	}

	var log map[string]interface{}
	json.Unmarshal([]byte(val), &log)

	return c.JSON(fiber.Map{
		"code":    200,
		"data":    log,
		"message": "Success",
		"status":  true,
	})
}

func CreateRiderStatus(c *fiber.Ctx) error {
	ctx := context.Background()

	var status models.RiderStatus
	if err := c.BodyParser(&status); err != nil {
		return c.Status(400).JSON(fiber.Map{
			"status":  false,
			"message": "Invalid request body",
		})
	}

	if status.UserID == 0 || status.Status == "" {
		return c.Status(400).JSON(fiber.Map{
			"status":  false,
			"message": "userid and status required",
		})
	}

	key := fmt.Sprintf("rider_status:%d", status.UserID)

	data, _ := json.Marshal(status)

	// ✅ Store latest status
	err := db.Rdb.Set(ctx, key, data, 0).Err()
	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to store status",
		})
	}

	// 🔥 ADD THIS (MISSING PART)
	err = db.Rdb.ZAdd(ctx, "rider_status_all", redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: key,
	}).Err()

	if err != nil {
		return c.Status(500).JSON(fiber.Map{
			"status":  false,
			"message": "Failed to index status",
		})
	}

	return c.JSON(fiber.Map{
		"status":  true,
		"message": "Rider status updated",
	})
}

func GetRiderStatus(c *fiber.Ctx) error {
	ctx := context.Background()

	userIDStr := c.Query("userid")
	pageStr := c.Query("page")
	pageSizeStr := c.Query("pagesize")

	// 🔹 CASE 1: Single user
	if userIDStr != "" {
		key := fmt.Sprintf("rider_status:%s", userIDStr)

		val, err := db.Rdb.Get(ctx, key).Result()
		if err != nil {
			return c.Status(http.StatusNotFound).JSON(fiber.Map{
				"status":  false,
				"code":    http.StatusNotFound,
				"message": "Status not found",
				"data":    []interface{}{},
			})
		}

		var data map[string]interface{}
		json.Unmarshal([]byte(val), &data)

		return c.Status(http.StatusOK).JSON(fiber.Map{
			"status":  true,
			"code":    http.StatusOK,
			"message": "Success",
			"data":    data,
		})
	}

	// 🔹 CASE 2: ALL users (with optional pagination)

	page, _ := strconv.Atoi(pageStr)
	pageSize, _ := strconv.Atoi(pageSizeStr)

	var start, end int64

	if page > 0 && pageSize > 0 {
		offset := (page - 1) * pageSize
		start = int64(offset)
		end = int64(offset + pageSize - 1)
	} else {
		start = 0
		end = -1 // return ALL
	}

	// 🔥 Fetch all status keys from global ZSET
	keys, err := db.Rdb.ZRevRange(ctx, "rider_status_all", start, end).Result()
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to fetch statuses",
			"data":    []interface{}{},
		})
	}

	// 🔥 Fast fetch using MGET
	values, err := db.Rdb.MGet(ctx, keys...).Result()
	if err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"status":  false,
			"code":    http.StatusInternalServerError,
			"message": "Failed to fetch data",
			"data":    []interface{}{},
		})
	}

	var result []map[string]interface{}

	for _, val := range values {
		if val == nil {
			continue
		}

		var item map[string]interface{}
		json.Unmarshal([]byte(val.(string)), &item)

		result = append(result, item)
	}

	return c.Status(http.StatusOK).JSON(fiber.Map{
		"status":  true,
		"code":    http.StatusOK,
		"message": "Success",
		"data":    result,
	})
}
