package repositories

import (
	"context"
	"fmt"
	"nearle/models"
	"strconv"

	firebase "firebase.google.com/go"
	"firebase.google.com/go/messaging"
	"google.golang.org/api/option"
	"gorm.io/gorm"
)

type UtilsRepository interface {
	GetApptypes(tag string) ([]models.Apptypes, error)
	SendNotification(token string, notification models.FcmNotification, data map[string]string) error
	GetSubcategories(moduleid int, categoryid int) ([]models.Appsubcategories, error)
	GetApplocations(aid int) ([]models.Applocations, error)
	GetApplocationConfig(aid int) ([]models.Applocations, error)
	GetAppConfig(configID int) (models.Appconfig, error)
	GetAppCategory() ([]models.AppCategory, error)
}

type utilsRepository struct {
	db *gorm.DB
}

func NewUtilsRepository(db *gorm.DB) UtilsRepository {
	return &utilsRepository{db: db}
}

func (r *utilsRepository) GetApptypes(tag string) ([]models.Apptypes, error) {

	var data []models.Apptypes

	q1 := `Select * from app_types where status ='Active' and tag='` + tag + `'`

	print(q1)

	err := r.db.Raw(q1).Find(&data).Error
	if err != nil {
		return nil, err
	}

	return data, nil

}

func (r *utilsRepository) SendNotification(token string, notification models.FcmNotification, data map[string]string) error {

	opt := option.WithCredentialsFile("nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json")
	app, err := firebase.NewApp(context.Background(), nil, opt)
	if err != nil {
		return fmt.Errorf("error initializing Firebase app: %v", err)
	}

	client, err := app.Messaging(context.Background())
	if err != nil {
		return fmt.Errorf("error getting Messaging client: %v", err)
	}

	message := &messaging.Message{
		Token: token,
		Notification: &messaging.Notification{
			Title: notification.Title,
			Body:  notification.Body,
		},
		Android: &messaging.AndroidConfig{
			Priority: "high",
			Notification: &messaging.AndroidNotification{
				Sound: "ring",
			},
		},
		Data: data,
	}

	_, err = client.Send(context.Background(), message)
	if err != nil {
		return fmt.Errorf("error sending FCM message: %v", err)
	}

	return nil
}

func (r *utilsRepository) GetSubcategories(moduleid int, categoryid int) ([]models.Appsubcategories, error) {
	var data []models.Appsubcategories

	query := `
	SELECT a.subcategoryid,a.categoryid,a.subcategoryname,b.categoryname,a.status,c.moduleid
	FROM app_subcategory a
	INNER JOIN app_category b ON a.categoryid = b.categoryid
	INNER JOIN app_module c ON a.categoryid = c.categoryid
	WHERE 1=1`

	var params []interface{}

	if moduleid != 0 {
		query += " AND c.moduleid = ?"
		params = append(params, moduleid)
	}

	if categoryid != 0 {
		query += " AND a.categoryid = ?"
		params = append(params, categoryid)
	}

	if err := r.db.Raw(query, params...).Scan(&data).Error; err != nil {
		return nil, err
	}
	print(query)
	return data, nil
}

func (r *utilsRepository) GetApplocations(aid int) ([]models.Applocations, error) {
	var data []models.Applocations

	q1 := `Select * from app_location where status='Active'`
	if aid != 0 {
		q1 += ` and applocationid = ?`
		params := []interface{}{aid}
		err := r.db.Raw(q1, params...).Scan(&data).Error
		if err != nil {
			return nil, err
		}
	} else {
		err := r.db.Raw(q1).Scan(&data).Error
		if err != nil {
			return nil, err
		}
	}
	print(q1)
	return data, nil
}

func (r *utilsRepository) GetApplocationConfig(aid int) ([]models.Applocations, error) {
	var data []models.Applocations
	var q1, q2 string

	if aid != 0 {
		q1 = `SELECT * FROM app_location WHERE status='Active' AND applocationid=` + strconv.Itoa(aid)
	} else {
		q1 = `SELECT * FROM app_location WHERE status='Active'`
	}

	if err := r.db.Raw(q1).Scan(&data).Error; err != nil {
		return nil, err
	}

	for i := range data {
		q2 = `
			SELECT a.userid, a.userfcmtoken, b.notify, b.applocationid
			FROM app_users a
			INNER JOIN app_locationconfig b ON a.userid = b.userid
			WHERE b.notify='true' AND b.applocationid=` + strconv.Itoa(data[i].Applocationid)

		var users []models.Applocationadmins
		if err := r.db.Raw(q2).Scan(&users).Error; err != nil {
			return nil, err
		}

		data[i].Applocationadmins = users
	}
	print(q1)
	return data, nil
}

func (r *utilsRepository) GetAppConfig(configID int) (models.Appconfig, error) {
	var data models.Appconfig
	var q1 string

	if configID != 0 {
		q1 = `SELECT a.configid,a.Appname,a.paymentdevkey,a.paymentlivekey,a.fcmkey,a.googleapikey,a.applocationradius,
		       b.providerid,b.providerapi,b.providerkey
		       FROM app_config a 
		       LEFT JOIN smsproviders b ON a.smsproviderid=b.providerid
		       WHERE a.configid=` + strconv.Itoa(configID)
	} else {
		q1 = `SELECT a.configid,a.Appname,a.paymentdevkey,a.paymentlivekey,a.fcmkey,a.googleapikey,a.applocationradius,
		       b.providerid,b.providerapi,b.providerkey 
		       FROM app_config a 
		       LEFT JOIN smsproviders b ON a.smsproviderid=b.providerid 
		       ORDER BY configid ASC`
	}

	fmt.Println(q1)
	if err := r.db.Raw(q1).Find(&data).Error; err != nil {
		return data, err
	}
	return data, nil
}

func (r *utilsRepository) GetAppCategory() ([]models.AppCategory, error) {
	var data []models.AppCategory

	query := `SELECT * FROM app_category WHERE status = 'Active' ORDER BY sortorder ASC`

	if err := r.db.Raw(query).Scan(&data).Error; err != nil {
		return nil, err
	}

	return data, nil
}
