package handlers

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/fiskerinc/cloud-services/services/depot/services"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/logger"
	"github.com/fiskerinc/cloud-services/pkg/redis"

	"github.com/pkg/errors"
)

func HMIInit(db *services.DB, id string, data []byte) error {
	fmt.Printf("HMIInit()")
	client := services.RedisClientPool().GetFromPool()
	defer client.Close()

	var sessionPayload common.HMISessionData
	err := json.Unmarshal(data, &sessionPayload)
	if err != nil {
		return errors.WithStack(err)
	}

	logger.Info().Msgf("Initialize HMI session in Redis for %s with ID %s", id, sessionPayload.SessionID)
	err = addHMISession(client, id)
	if err != nil {
		logger.Warn().Str("id", id).Err(err).Send()
	}

	err = addHMISessionID(client, id, sessionPayload.SessionID)
	if err != nil {
		logger.Warn().Str("id", id).Err(err).Send()
	}

	if sessionPayload.Salt != "" {
		err = addHMISaltID(client, id, sessionPayload.Salt)
		if err != nil {
			logger.Warn().Str("id", id).Err(err).Send()
		}
	}

	err = sendSettingsHMI(client, db, id)
	if err != nil {
		logger.Warn().Str("id", id).Err(err).Send()
		return err
	}

	return nil
}

func addHMISession(client redis.Client, id string) error {
	_, err := client.Execute("SADD", redis.HMISessionsKey(), id)
	return err
}

func addHMISessionID(client redis.Client, id string, sessionID string) error {
	_, err := client.Execute("SET", redis.HMISessionKey(id), sessionID)
	return err
}

func addHMISaltID(client redis.Client, id string, salt string) error {
	_, err := client.Execute("SET", redis.HMISaltKey(id), salt)
	return err
}

func sendSettingsHMI(client redis.Client, db *services.DB, vin string) error {

	settings, err := getSettings(db, vin)
	if err != nil {
		return err
	}

	if len(settings) == 0 {
		logger.Info().Msgf("no settings to send for car %s", vin)
		return nil
	}

	return client.SafePublishMessage(common.HMI.Key(vin),
		common.Message{
			Handler: "car_settings",
			Data:    settings,
		},
	)
}

func clearSettings(settings []common.CarSetting) {
	cTime := time.Now()
	for i, s := range settings {
		s.CreatedAt = nil
		if s.UpdatedAt == nil {
			s.UpdatedAt = &cTime
		}
		settings[i] = s
	}
}
