package utils

import (
	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/validator"
	"github.com/fiskerinc/cloud-services/pkg/vindecoder"
	"github.com/pkg/errors"
	"github.com/fiskerinc/cloud-services/pkg/utils/envtool"
)

var (
	defaultCountry    = envtool.GetEnv("DEFAULT_VEH_COUNTRY", "Unknown")
	defaultModel      = envtool.GetEnv("DEFAULT_VEH_MODEL", "Ocean")
	defaultYear       = envtool.GetEnvInt("DEFAULT_VEH_YEAR", 2022)
	defaultTrim       = envtool.GetEnv("DEFAULT_VEH_TRIM", "Unknown")
	defaultPowertrain = envtool.GetEnv("DEFAULT_VEH_POWERTRAIN", "Unknown")
	defaultRestraint  = envtool.GetEnv("DEFAULT_VEH_RESTRAINT", "Unknown")
	defaultBodyType   = envtool.GetEnv("DEFAULT_VEH_BODY_TYPE", "Unknown")
)

func ParseVIN(vin string) (*common.Car, error) {
	if vin == "" {
		return nil, errors.Errorf("vin is empty")
	}

	vinInfo, _ := vindecoder.DecodeVIN(vin)

	// for all vins, do a simple regex validation
	valid := validator.ValidateVINSimple(vin)
	if !valid {
		return nil, errors.Errorf("vin %v is invalid", vin)
	}

	// for all vins, do a checksum validation
	if !vinInfo.IsValid {
		return nil, errors.Errorf("vin %v is invalid", vin)
	}

	var defaultRegion common.RegionCode
	switch defaultRestraint {
	case "US Specs":
		defaultRegion = common.US
	case "EU Specs":
		defaultRegion = common.EU
	default:
		defaultRegion = common.US
	}

	if vinInfo.Manufacturer != "Fisker GmbH" {
		// for non-Fisker vins, use default values
		return &common.Car{
			VIN:        vin,
			Region:     defaultRegion,
			Country:    defaultCountry,
			Model:      defaultModel,
			Trim:       defaultTrim,
			Year:       defaultYear,
			Powertrain: defaultPowertrain,
			Restraint:  defaultRestraint,
			BodyType:   defaultBodyType,
		}, nil
	}

	if vinInfo.Country == "" {
		vinInfo.Country = defaultCountry
	}
	if vinInfo.Model == "" {
		vinInfo.Model = defaultModel
	}
	if vinInfo.Trim == "" {
		vinInfo.Trim = defaultTrim
	}
	if vinInfo.Powertrain == "" {
		vinInfo.Powertrain = defaultPowertrain
	}
	if vinInfo.Restraint == "" {
		vinInfo.Restraint = defaultRestraint
	}
	if vinInfo.BodyType == "" {
		vinInfo.BodyType = defaultBodyType
	}

	var region common.RegionCode
	switch vinInfo.Restraint {
	case "US Specs":
		region = common.US
	case "EU Specs":
		region = common.EU
	}

	return &common.Car{
		VIN:        vin,
		Region:     region,
		Country:    vinInfo.Country,
		Model:      vinInfo.Model,
		Trim:       vinInfo.Trim,
		Year:       vinInfo.Year,
		Powertrain: vinInfo.Powertrain,
		Restraint:  vinInfo.Restraint,
		BodyType:   vinInfo.BodyType,
	}, nil
}

func ParseVINs(vins []string) ([]*common.Car, error) {
	if len(vins) == 0 {
		return nil, errors.Errorf("vin list is empty")
	}

	var cars []*common.Car
	var invalidVINs []string

	for _, vin := range vins {
		car, err := ParseVIN(vin)
		if err != nil {
			invalidVINs = append(invalidVINs, vin)
		} else {
			cars = append(cars, car)
		}
	}

	if len(invalidVINs) > 0 {
		return cars, errors.Errorf("vins %+q are invalid", invalidVINs)
	}

	return cars, nil
}
