package utils

import (
	"testing"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/pkg/errors"
	"github.com/stretchr/testify/assert"
)

func TestParseVIN(t *testing.T) {
	tests := []struct {
		name        string
		testVin     string
		expectedCar *common.Car
		expectedErr error
	}{
		{
			name:        "empty vin",
			testVin:     "",
			expectedCar: nil,
			expectedErr: errors.Errorf("vin is empty"),
		},
		{
			name:        "invalid vin",
			testVin:     "XXXXXXXXXXXXXXXXX",
			expectedCar: nil,
			expectedErr: errors.Errorf("vin XXXXXXXXXXXXXXXXX is invalid"),
		},
		{
			name:        "invalid fisker vin",
			testVin:     "VCFQQQQQQQQQQQQQQ",
			expectedCar: nil,
			expectedErr: errors.Errorf("vin VCFQQQQQQQQQQQQQQ is invalid"),
		},
		{
			name:        "invalid checksum Fisker vin",
			testVin:     "VCF1ZBU28PG159581",
			expectedCar: nil,
			expectedErr: errors.Errorf("vin VCF1ZBU28PG159581 is invalid"),
		},
		{
			name:    "non-fisker vin",
			testVin: "1G1FP87S3GN100062",
			expectedCar: &common.Car{
				VIN:        "1G1FP87S3GN100062",
				Country:    defaultCountry,
				Model:      defaultModel,
				Trim:       defaultTrim,
				Year:       defaultYear,
				Powertrain: defaultPowertrain,
				Restraint:  defaultRestraint,
				BodyType:   defaultBodyType,
			},
			expectedErr: nil,
		},
		{
			name:    "fisker vin",
			testVin: "VCF1EBE25PG001013",
			expectedCar: &common.Car{
				VIN:        "VCF1EBE25PG001013",
				Country:    "Austria",
				Model:      "Ocean",
				Trim:       "Extreme",
				Year:       2023,
				Powertrain: "LBP/DM/AWD",
				Restraint:  "EU Specs",
				BodyType:   "5-Door MPV, 5-Seater, Class E",
			},
			expectedErr: nil,
		},
	}

	for _, test := range tests {
		t.Log(test.name)

		car, err := ParseVIN(test.testVin)

		if test.expectedErr != nil {
			assert.Equal(t, test.expectedErr.Error(), err.Error())
		} else {
			assert.Nil(t, err)
		}

		if test.expectedCar != nil {
			assert.Equal(t, test.expectedCar.VIN, car.VIN)
			assert.Equal(t, test.expectedCar.Country, car.Country)
			assert.Equal(t, test.expectedCar.Model, car.Model)
			assert.Equal(t, test.expectedCar.Trim, car.Trim)
			assert.Equal(t, test.expectedCar.Year, car.Year)
			assert.Equal(t, test.expectedCar.Powertrain, car.Powertrain)
			assert.Equal(t, test.expectedCar.Restraint, car.Restraint)
			assert.Equal(t, test.expectedCar.BodyType, car.BodyType)
		} else {
			assert.Nil(t, car)
		}
	}
}

func TestParseVINs(t *testing.T) {
	tests := []struct {
		name         string
		testVins     []string
		expectedCars []*common.Car
		expectedErr  error
	}{
		{
			name:     "valid vin",
			testVins: []string{"VCF1UBE22PG888888"},
			expectedCars: []*common.Car{{
				VIN:        "VCF1UBE22PG888888",
				Country:    "Austria",
				Model:      "Ocean",
				Trim:       "Extreme",
				Year:       2023,
				Powertrain: "LBP/DM/AWD",
				Restraint:  "EU Specs",
				BodyType:   "5-Door MPV, 5-Seater, Class E",
			}},
			expectedErr: errors.Errorf(`vins ["VCF1UBE22PG888888"] are invalid`),
		},
		{
			name:         "empty vin list",
			testVins:     nil,
			expectedCars: nil,
			expectedErr:  errors.Errorf("vin list is empty"),
		},
		{
			name:         "invalid vin",
			testVins:     []string{"XXXXXXXXXXXXXXXXX"},
			expectedCars: nil,
			expectedErr:  errors.Errorf("vins [\"XXXXXXXXXXXXXXXXX\"] are invalid"),
		},
		{
			name:     "valid vin",
			testVins: []string{"VCF1EBE25PG001013"},
			expectedCars: []*common.Car{{
				VIN:        "VCF1EBE25PG001013",
				Country:    "Austria",
				Model:      "Ocean",
				Trim:       "Extreme",
				Year:       2023,
				Powertrain: "LBP/DM/AWD",
				Restraint:  "EU Specs",
				BodyType:   "5-Door MPV, 5-Seater, Class E",
			}},
			expectedErr: nil,
		},
		{
			name:     "partially valid vins",
			testVins: []string{"VCF1EBE25PG001013", "XXXXXXXXXXXXXXXXX"},
			expectedCars: []*common.Car{{
				VIN:        "VCF1EBE25PG001013",
				Country:    "Austria",
				Model:      "Ocean",
				Trim:       "Extreme",
				Year:       2023,
				Powertrain: "LBP/DM/AWD",
				Restraint:  "EU Specs",
				BodyType:   "5-Door MPV, 5-Seater, Class E",
			}},
			expectedErr: errors.Errorf("vins [\"XXXXXXXXXXXXXXXXX\"] are invalid"),
		},
	}

	for _, test := range tests {
		t.Log(test.name)

		cars, err := ParseVINs(test.testVins)

		if test.expectedErr != nil {
			assert.Equal(t, test.expectedErr.Error(), err.Error())
		} else {
			assert.Nil(t, err)
		}

		for i, car := range cars {
			if test.expectedCars[i] != nil {
				assert.Equal(t, test.expectedCars[i].VIN, car.VIN)
				assert.Equal(t, test.expectedCars[i].Country, car.Country)
				assert.Equal(t, test.expectedCars[i].Model, car.Model)
				assert.Equal(t, test.expectedCars[i].Trim, car.Trim)
				assert.Equal(t, test.expectedCars[i].Year, car.Year)
				assert.Equal(t, test.expectedCars[i].Powertrain, car.Powertrain)
				assert.Equal(t, test.expectedCars[i].Restraint, car.Restraint)
				assert.Equal(t, test.expectedCars[i].BodyType, car.BodyType)
			} else {
				assert.Nil(t, car)
			}
		}
	}
}
