package handlers

import (
	"encoding/json"
	"errors"

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

	"github.com/fiskerinc/cloud-services/pkg/common"
	fv "github.com/fiskerinc/cloud-services/pkg/flashpackversion"
	"github.com/fiskerinc/cloud-services/pkg/logger"
	"github.com/fiskerinc/cloud-services/pkg/validator"
)

func UpdateCarState(db *services.DB, vin string, data []byte) error {
	logger.Debug().Msgf("UpdateCarState %s", vin)
	var update common.CarStateUpdate

	err := json.Unmarshal(data, &update)
	if err != nil {
		return err
	}

	err = validator.ValidateStruct(&update)
	if err != nil {
		logger.Err(err).Interface("CarStateUpdate", update).Str("CarStateUpdateByteValue as string", string(data)).Send()
		return err
	}

	return processUpdateCarStateECUs(db, vin, update.ECUs)
}

func processUpdateCarStateECUs(db *services.DB, vin string, ecus map[string]common.CarECU) error {
	cache := services.GetCarEcuCache()
	insert := []common.CarECU{}
	errs := []error{}

	for name, ecu := range ecus {
		ecu.VIN = vin
		ecu.ECU = name
		err := validator.ValidateStruct(&ecu)
		if err != nil {
			logger.Error().Msgf("invalid CarECU %v", err)
			errs = append(errs, err)
			continue
		}

		if !cache.Exists(ecu.CacheKey(), ecu.HashValues()) {
			insert = append(insert, ecu)
		}
	}

	if len(insert) == 0 {
		return combineErrors(errs)
	}

	err := fv.InsertCarECUsAndUpdateFlashpackVersion(db.GetCars(), db.GetCarVersionsLog(), vin, insert)
	if err != nil {
		errs = append(errs, err)
	}

	return combineErrors(errs)
}

func combineErrors(errs []error) error {
	if len(errs) == 0 {
		return nil
	}
	errString := errs[0].Error()
	for i := 1; i < len(errs); i++ {
		errString += " " + errs[i].Error()
	}
	return errors.New(errString)
}
