package handlers

import (
	"github.com/fiskerinc/cloud-services/services/depot/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/pkg/errors"
)

// get vehicle settings
func getSettings(db *services.DB, vin string) ([]common.CarSetting, error) {
	settings, err := db.GetCars().GetVehicleSpecificSettings(&common.CarToDriver{
		VIN: vin,
	})
	if err != nil {
		return nil, errors.WithStack(err)
	}

	osVersionSetting, err := getOSVersion(vin)
	if err == nil && osVersionSetting != nil {
		settings = append(settings, *osVersionSetting)
	} else {
		logger.Error().Msgf("failed to get os version %v", err)
	}

	flashpackNumber, err := getFlashpackNumber(vin)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	if flashpackNumber != nil {
		settings = append(settings, *flashpackNumber)
	} else {
		logger.Warn().Msgf("no flashpack number yet for vin %s because not enough ECUs have been updated", vin)
	}

	certNeedsRenewal, err := services.GetCertService().CheckCertificateNeedsRenewal(vin, common.CertICC)
	if err != nil {
		logger.Error().Msgf("failed to check for certificate renewal %v", err)
	} else if certNeedsRenewal {
		logger.Debug().Msg("ICC cert for vin " + vin + " is out of date")

		settings = append(settings, common.CarSetting{
			Name:  "certificates",
			Value: "expired",
			Type:  "string",
		})
	}

	clearSettings(settings)
	return settings, nil
}

// Get the OS version given a vin
func getOSVersion(vin string) (*common.CarSetting, error) {
	sumsVersion, err := getSUMS(vin)
	if err != nil {
		return nil, err
	}

	sumsDB := services.GetDB().GetUpdateManifestSUMSVersions()
	sums, err := sumsDB.Select(sumsVersion)
	if err != nil {
		logger.Error().Msgf("can not load SUMS, %v", err)
		return nil, err
	}

	cs := common.CarSetting{
		Name:  "os_version",
		Value: sums.OSVersion,
		Type:  "string",
	}
	cs.CreatedAt = sums.CreatedAt
	cs.UpdatedAt = sums.UpdatedAt

	return &cs, nil
}

// Get the SUMS version from update manifest for a given vin
func getSUMS(vin string) (sumsVersion string, err error) {
	carsDB := services.GetDB().GetCars()
	car, err := carsDB.SelectByVIN(vin)
	if err != nil {
		logger.Err(err).Msgf("failed in getSUMS(vin string) for car %s to fetch car", vin)
		return
	}

	return car.SUMSVersion, err
}

// Get the flash pack number
func getFlashpackNumber(vin string) (*common.CarSetting, error) {
	cars := services.GetDB().GetCars()

	car, err := cars.SelectByVIN(vin)
	if err != nil {
		return nil, err
	}

	flashpackNumber, err := fv.FindCurrentFlashpackVersionForCar(cars, *car)
	if err != nil {
		return nil, err
	}

	if flashpackNumber != "" {
		cs := &common.CarSetting{
			Name:  "flashpack_number",
			Value: flashpackNumber,
			Type:  "string",
		}

		return cs, nil
	}

	return nil, nil
}
