package vindecoder_test

import (
	"strings"
	"testing"

	"github.com/fiskerinc/cloud-services/pkg/testhelper"
	"github.com/fiskerinc/cloud-services/pkg/vindecoder"
)

var vwGer2013Valid = "WVWBN7AN6DE546002"
var vwGer2013Invalid1 = "WVWBN7AN1DE546002"
var vwGer2013Invalid2 = "WVWBN7AN6DE54600"
var miniGer2009Valid = "WMWMS335X9TY38985"
var bugatFra1998Valid = "VF9SP3V31JM795073"
var dodgeUsa1998Valid = "1B3ES42C4WD736523"
var fiskerVinValid = "VCF1ZBU23PG001209"

// TEMP
var fskUsa2021Valid = "1F1BN7AN7MA000001"

// TEMP

//var unkJap2013Valid = "JS1GR7MA7D2101136"
//var audiGer2012Valid = "WAUFFAFM3CA000000"

func TestVinDecoderCountry(t *testing.T) {
	// there should be more tests for cases where second character is 1-9, 0, but it's hard to find valid vins

	// USA
	vi1, _ := vindecoder.DecodeVIN(dodgeUsa1998Valid)
	if !strings.Contains(vi1.Country, "United States") {
		t.Errorf(testhelper.TestErrorTemplate, dodgeUsa1998Valid, "United States", vi1.Country)
	}

	// Germany
	vi2, _ := vindecoder.DecodeVIN(vwGer2013Valid)
	if !strings.Contains(vi2.Country, "Germany") {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid, "Germany", vi2.Country)
	}
	valid := vindecoder.ValidateVINSimple(fiskerVinValid)
	if !valid {
		t.Errorf(testhelper.TestErrorTemplate, fiskerVinValid, "Invalid", vi2.Country)

	}

}

func TestVinDecoderWmi(t *testing.T) {
	// normal
	vi1, _ := vindecoder.DecodeVIN(vwGer2013Valid)
	if !strings.Contains(vi1.Manufacturer, "Volkswagen") {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid, "Volkswagen", vi1.Manufacturer)
	}

	// small production
	vi2, _ := vindecoder.DecodeVIN(bugatFra1998Valid)
	if !strings.Contains(vi2.Manufacturer, "Bugatti") {
		t.Errorf(testhelper.TestErrorTemplate, bugatFra1998Valid, "Bugatti", vi2.Manufacturer)
	}

	// wild card
	mfg1 := vindecoder.LookupManufacturerByWmiCode("4F3")
	if !strings.Contains(mfg1, "Mazda") {
		t.Errorf(testhelper.TestErrorTemplate, "4F3", "Mazda", mfg1)
	}

	// normal unknown wmi
	mfg2 := vindecoder.LookupManufacturerByWmiCode("JM2")
	if mfg2 != "JM2" {
		t.Errorf(testhelper.TestErrorTemplate, "JM2", "JM2", mfg2)
	}

	// TEMP
	// normal
	viFsk, _ := vindecoder.DecodeVIN(fskUsa2021Valid)
	if !strings.Contains(viFsk.Manufacturer, "Fisker") {
		t.Errorf(testhelper.TestErrorTemplate, fskUsa2021Valid, "Fisker", viFsk.Manufacturer)
	}
	// TEMP
}

func TestVinDecoderSerialNumber(t *testing.T) {
	// normal
	vi1, _ := vindecoder.DecodeVIN(vwGer2013Valid)
	if vi1.SerialNumber != "546002" {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid, "546002", vi1.SerialNumber)
	}

	// small production
	vi2, _ := vindecoder.DecodeVIN(bugatFra1998Valid)
	if vi2.SerialNumber != "073" {
		t.Errorf(testhelper.TestErrorTemplate, bugatFra1998Valid, "073", vi2.SerialNumber)
	}
}

func TestVinDecoderCheckDigit(t *testing.T) {
	// valid
	vi1, ok := vindecoder.DecodeVIN(vwGer2013Valid)
	if ok == false {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid, true, ok)
	}
	if !vi1.IsValid {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid, true, vi1.IsValid)
	}

	// valid - lowercase
	var vwGer2013Valid_lower = strings.ToLower(vwGer2013Valid)
	vi1a, ok := vindecoder.DecodeVIN(vwGer2013Valid_lower)
	if ok == false {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid_lower, true, ok)
	}
	if !vi1a.IsValid {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid_lower, true, vi1a.IsValid)
	}

	// invalid
	vi2, ok := vindecoder.DecodeVIN(vwGer2013Invalid1)
	if ok == true {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Invalid1, false, ok)
	}
	if vi2.IsValid {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Invalid1, false, vi2.IsValid)
	}

	vi3, ok := vindecoder.DecodeVIN(vwGer2013Invalid2)
	if ok == true {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Invalid2, false, ok)
	}
	if vi3.IsValid {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Invalid2, false, vi3.IsValid)
	}
}

func TestVinDecoderYear(t *testing.T) {
	// before 2010
	vi1, _ := vindecoder.DecodeVIN(miniGer2009Valid)
	if vi1.Year != 2009 {
		t.Errorf(testhelper.TestErrorTemplate, miniGer2009Valid, 2013, vi1.Year)
	}

	// after 2010
	vi2, _ := vindecoder.DecodeVIN(vwGer2013Valid)
	if vi2.Year != 2013 {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid, 2013, vi2.Year)
	}
}

func TestVinDecoderModelDetails(t *testing.T) {
	vi, _ := vindecoder.DecodeVIN(vwGer2013Valid)
	if vi.ModelDetails != "BN7AN" {
		t.Errorf(testhelper.TestErrorTemplate, vwGer2013Valid, "BN7AN", vi.ModelDetails)
	}
}

func TestNextVin(t *testing.T) {
	// test vin generation
	startVin := "WVWBN7AN6DE546002"
	nextVin, err := vindecoder.NextVIN(startVin)
	if err != nil {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "nil", err)
	}
	if strings.LastIndex(nextVin, "546003") < 0 {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "WVWBN7AN*DE546003", nextVin)
	}

	startVin = "WVWBN7AN6DE546XX9"
	nextVin, err = vindecoder.NextVIN(startVin)
	if err != nil {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "nil", err)
	}
	if strings.LastIndex(nextVin, "546X00") < 0 {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "WVWBN7AN6DE546X00", nextVin)
	}

	startVin = "WVWBN7AN6DE546999"
	nextVin, err = vindecoder.NextVIN(startVin)
	if err != nil {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "nil", err)
	}
	if strings.LastIndex(nextVin, "547000") < 0 {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "WVWBN7AN6DE547000", nextVin)
	}

	startVin = "WVWBN7AN6DE999999"
	nextVin, err = vindecoder.NextVIN(startVin)
	if err == nil {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "overflow", "nil")
	}
	if strings.LastIndex(nextVin, "000000") < 0 {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "WVWBN7AN6DE000000", nextVin)
	}

	startVin = "WVWBN7AN6DE999995"
	nextVins, err := vindecoder.NextNVINs(startVin, 10)
	if err == nil {
		t.Errorf(testhelper.TestErrorTemplate, startVin, "rollover", "nil")
	}
	if len(nextVins) != 10 {
		t.Errorf(testhelper.TestErrorTemplate, startVin, 10, len(nextVins))
	}
}


func TestEmptyVIN(t *testing.T){
	ok := vindecoder.ValidateVINSimple("")
	if ok {
		t.Error("Expected Invalid VIN")
	}
}