package models

import (
	"errors"
	"fmt"

	"forge.grandlyon.com/web-et-numerique/llle_project/backoffice-server/internal/common"
	"github.com/meilisearch/meilisearch-go"
	"gorm.io/driver/mysql"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

type DataHandler struct {
	sqlClient   *gorm.DB
	meiliClient *meilisearch.Client
}

var (
	dbUser     = common.StringValueFromEnv("DATABASE_USER", "")
	dbPassword = common.StringValueFromEnv("DATABASE_PASSWORD", "")
	dbName     = common.StringValueFromEnv("DATABASE_NAME", "")
	dbHost     = common.StringValueFromEnv("DATABASE_HOST", "")
)

// NewDataHandler init a DataHandler and returns a pointer to it
func NewDataHandler() *DataHandler {
	// SQL setup
	var sqlClient *gorm.DB
	var err error
	if dbUser == "" || dbPassword == "" || dbName == "" {
		sqlClient, err = gorm.Open(sqlite.Open("backoffice.db"), &gorm.Config{})
		if err != nil {
			panic("failed to connect sqlite database")
		}
	} else {
		dsn := fmt.Sprintf("%v:%v@tcp(%v:3306)/%v?charset=utf8mb4&parseTime=True&loc=Local", dbUser, dbPassword, dbHost, dbName)
		sqlClient, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
		if err != nil {
			panic("failed to connect MySQL database")
		}
	}

	// Migrate the schema
	sqlClient.AutoMigrate(&MailSubject{})
	sqlClient.AutoMigrate(&MonthlyInfo{})
	sqlClient.AutoMigrate(&MonthlyNews{})
	sqlClient.AutoMigrate(&Poll{})
	sqlClient.AutoMigrate(&PartnersInfo{})
	sqlClient.AutoMigrate(&CustomPopup{})
	sqlClient.AutoMigrate(&Price{})
	sqlClient.AutoMigrate(&Consent{})

	// Check if partners info already exists
	var partnersInfo PartnersInfo
	err = sqlClient.First(&partnersInfo).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		// Create default partner status
		sqlClient.Create(&PartnersInfo{
			GRDFFailure:           false,
			EnedisFailure:         false,
			EGLFailure:            false,
			NotificationActivated: false,
		})
	}

	// Check if custom popup already exists
	var customPopup CustomPopup
	err = sqlClient.First(&customPopup).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		// Create default custom popup
		sqlClient.Create(&CustomPopup{
			PopupEnabled: false,
			Title:        "",
			Description:  "",
		})
	}

	// Meilisearch setup
	meiliClient := meilisearch.NewClient(meilisearch.ClientConfig{
		Host:   common.StringValueFromEnv("MEILI_HOST", ""),
		APIKey: common.StringValueFromEnv("MEILI_MASTER_KEY", ""),
	})

	settings := meilisearch.Settings{
		DisplayedAttributes: []string{
			"ID",
			"CreatedAt",
			"firstname",
			"lastname",
			"pointID",
		},
		SearchableAttributes: []string{
			"pointID",
			"lastname",
			"firstname",
		},
		RankingRules: []string{
			"words",
			"typo",
			"proximity",
			"attribute",
			"sort",
			"exactness",
		},
		TypoTolerance: &meilisearch.TypoTolerance{
			MinWordSizeForTypos: meilisearch.MinWordSizeForTypos{
				OneTypo:  4,
				TwoTypos: 8,
			},
		},
	}

	meiliClient.Index("consents").UpdateSettings(&settings)

	return &DataHandler{sqlClient: sqlClient, meiliClient: meiliClient}
}