package controllers

import (
	"context"
	"nearle/domain"
	"nearle/models"
	"nearle/utils"
	"net/http"

	"sync"

	firebase "firebase.google.com/go"
	"firebase.google.com/go/messaging"
	"github.com/gofiber/fiber/v2"
	"google.golang.org/api/option"
)

var (
	fcmApp     *firebase.App
	fcmClient  *messaging.Client
	fcmOnce    sync.Once
	fcmInitErr error
)

// getFCMClient handles the singleton initialization of Firebase
func getFCMClient() (*messaging.Client, error) {
	fcmOnce.Do(func() {
		ctx := context.Background()
		opt := option.WithCredentialsFile("nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json")

		app, err := firebase.NewApp(ctx, nil, opt)
		if err != nil {
			fcmInitErr = err
			return
		}
		fcmApp = app

		client, err := app.Messaging(ctx)
		if err != nil {
			fcmInitErr = err
			return
		}
		fcmClient = client
	})
	return fcmClient, fcmInitErr
}

func NotifyUser(c *fiber.Ctx) error {
	// Parse the request body
	var body struct {
		Token        string                 `json:"token"`
		Notification models.FcmNotification `json:"notification"`
		Data         map[string]string      `json:"data"`
	}

	if err := c.BodyParser(&body); err != nil {
		utils.Error("NotifyUser parsing body error", "error", err)
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"code":    http.StatusBadRequest,
			"message": err.Error(),
			"status":  false,
		})
	}

	// Use shared client instead of initializing on every request
	client, err := getFCMClient()
	if err != nil {
		utils.Error("NotifyUser Firebase initialization error", "error", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": "FCM Initialization error: " + err.Error(),
			"status":  false,
		})
	}

	// Construct the message
	message := &messaging.Message{
		Token: body.Token,
		Notification: &messaging.Notification{
			Title: body.Notification.Title,
			Body:  body.Notification.Body,
		},
		Android: &messaging.AndroidConfig{
			Priority: "high",
			Notification: &messaging.AndroidNotification{
				Sound: "ring",
			},
		},
		Data: body.Data,
	}

	// Send the message
	_, err = client.Send(context.Background(), message)
	if err != nil {
		utils.Error("NotifyUser FCM send error", "error", err)
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
			"code":    http.StatusInternalServerError,
			"message": err.Error(),
			"status":  false,
		})
	}

	// Return structured response
	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "FCM message sent successfully!",
		"status":  true,
	})
}

func NotifyUsers(c *fiber.Ctx) error {

	var data models.Notifications

	if err := c.BodyParser(&data); err != nil {
		utils.Error("NotifyUsers parsing body error", "error", err)
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"code":    http.StatusBadRequest,
			"message": err.Error(),
			"status":  false,
		})
	}

	result := domain.SendNotifications(data)

	if !result {
		utils.Error("NotifyUsers bulk send failed")
		return c.JSON(fiber.Map{
			"code":    http.StatusOK,
			"message": "Failed to send notifications",
			"status":  false,
		})

	}

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