package common

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"

	"github.com/fiskerinc/cloud-services/pkg/common/dbbasemodel"
)

type CarECU struct {
	VIN               string `json:"vin,omitempty" pg:",unique:vin_ecu" validate:"required,vin"`
	ECU               string `json:"ecu" pg:",unique:vin_ecu" validate:"required,max=100"`
	Version           string `json:"sw_version" validate:"max=255"`
	SerialNumber      string `json:"serial_number,omitempty" validate:"max=1024"`
	HWVersion         string `json:"hw_version,omitempty" validate:"max=1024"`
	BootLoaderVersion string `json:"boot_loader_version,omitempty" validate:"max=1024"`
	Fingerprint       string `json:"fingerprint,omitempty" validate:"max=1024"`
	// cloud/attendant/handlers/car_update_state.go JSON message config was renamed to code_data_string
	Config            string `json:"code_data_string,omitempty" pg:"code_data_string" validate:"max=2048"` // config was renamed to code_data_string
	Vendor            string `json:"vendor,omitempty" validate:"max=1024"`
	SupplierSWVersion string `json:"supplier_sw_version,omitempty" validate:"max=1024"`
	Epoch_usec        int64  `json:"epoch_usec" pg:"epoch_usec"`
	ASSYNumber        string `json:"assy_number,omitempty" pg:"assy_number"`
	dbbasemodel.DBModelBase
}

func (c *CarECU) CacheKey() string {
	return fmt.Sprintf("%s:%s", c.VIN, c.ECU)
}

func (c *CarECU) HashValues() string {
	data := []byte(fmt.Sprintf("%s:%s:%s:%s:%s:%s:%s:%s:%s", c.Version, c.SerialNumber, c.HWVersion, c.BootLoaderVersion, c.Fingerprint, c.Config, c.Vendor, c.SupplierSWVersion, c.ASSYNumber))
	hash := sha256.Sum256(data)
	signature := hex.EncodeToString(hash[:])
	return signature
}

// Ensure we always have the correct car_ecu name for OTA
func (c *CarECU) TransformECUName() {
	replacement, ok := OTAUpdateECUReplacement[c.ECU]
	if ok {
		c.ECU = replacement
	}
}

type CarECUFilter struct {
	VIN                  string
	ECUs                 []string
	Search               string
	Unique               bool
	FlashPackNumberExist bool
	HWVersionRequired    bool // Ensure that the hw_version has a value. This may not retrieve the latest entry for the ecu, but until we find out why hw_versions are being inserted as empty
}

type CarFlashpackVersion struct {
	Flashpack     string `json:"flashpack" validate:"required,numeric"`
	CarModel      string `json:"car_model" validate:"required"`
	CarTrim       string `json:"car_trim" validate:"required"`
	CarYear       int    `json:"car_year" validate:"required"`
	CarECUName    string `json:"car_ecu_name" validate:"required"`
	CarECUVersion string `json:"car_ecu_version" validate:"required"`
	dbbasemodel.DBModelBase
}

type CarECUVersion struct {
	CarECUName    string `json:"car_ecu_name"`
	CarECUVersion string `json:"car_ecu_version"`
}

type CarFlashpackVersionRequest struct {
	Flashpack string `json:"flashpack" validate:"required,numeric"`
	CarModel  string `json:"car_model" validate:"required"`
	CarTrim   string `json:"car_trim" validate:"required"`
	CarYear   int    `json:"car_year" validate:"required"`
}

type ECUVersionRequest struct {
	CarECUName    string `json:"car_ecu_name" validate:"required"`
	CarECUVersion string `json:"car_ecu_version" validate:"required"`
}

type CarFlashpackVersionAddRequest struct {
	Flashpack   string              `json:"flashpack" validate:"required,numeric"`
	CarModel    string              `json:"car_model" validate:"required"`
	CarTrim     string              `json:"car_trim" validate:"required"`
	CarYear     int                 `json:"car_year" validate:"required"`
	ECUVersions []ECUVersionRequest `json:"ecu_versions" validate:"required"`
}

type CarFlashpackVersionResponse struct {
	Flashpack string `json:"flashpack"`
	CarModel  string `json:"car_model"`
	CarTrim   string `json:"car_trim"`
	CarYear   int    `json:"car_year"`
}

type CarFlashpackVersionInfoResponse struct {
	Flashpack     string          `json:"flashpack"`
	NextFlashpack string          `json:"next_flashpack"`
	ECUVersions   []CarECUVersion `json:"ecu_versions"`
}
