package tmobile

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"reflect"
	"strings"
	"testing"
	"time"

	"github.com/fiskerinc/cloud-services/pkg/grpc/sms"
	"github.com/fiskerinc/cloud-services/pkg/tmobtokengen"
)

type mockTG struct {
	wasSet chan tmobtokengen.EHTSMap
}

func (c *mockTG) Generate(ehts tmobtokengen.EHTSMap) (string, error) {
	c.wasSet <- ehts

	return "generatedPopToken", nil
}

func (c *mockTG) ClientSecretAsAuthVal() string {
	return "clientSecret"
}

type mockHTTPClientAT struct {
	wasSet chan *http.Request
}

func (c *mockHTTPClientAT) Do(req *http.Request) (*http.Response, error) {
	c.wasSet <- req

	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(strings.NewReader(mockATjson)),
	}, nil
}

var mockATjson = `{
	"id_token": "generatedToken",
	"access_token": "generatedToken",
	"expires_in": 3600,
	"token_type": "type",
	"resource": "https://api.mob.com/",
	"refresh_token": "refreshToken",
	"scope": "scope"
}`

var mockUrlStr = "https://api.mob.com"

var mockUrl *url.URL

func init() {
	mockUrl, _ = url.Parse(mockUrlStr)
	b, _ := json.Marshal(mockSmsDetailsResponse)
	mockSmsDetailsJsonRes = string(b)
}

func TestTMobClient_AccessToken(t *testing.T) {
	mHTTP := &mockHTTPClientAT{wasSet: make(chan *http.Request, 1)}
	mTG := &mockTG{wasSet: make(chan tmobtokengen.EHTSMap, 1)}
	cl := &TMobClient{
		client:  mHTTP,
		tg:      mTG,
		baseURL: mockUrl,
	}

	atr, err := cl.AccessToken(mockCtx)
	if err != nil {
		t.Errorf("AccessToken() should have succeeded: %v", err)
	}

	if atr.AccessToken != "generatedToken" {
		t.Errorf("AccessToken() should have returned generated token")
	}

	select {
	case ehts := <-mTG.wasSet:
		if ehts["Authorization"] != "clientSecret" {
			t.Errorf("AccessToken() should have set Authorization header")
		}
		if ehts["uri"] != "/oauth2/v1/tokens" {
			t.Errorf("AccessToken() ehts should have set uri")
		}
		if ehts["http-method"] != "POST" {
			t.Errorf("AccessToken() ehts should have set method")
		}
		if len(ehts) != 3 {
			t.Errorf("AccessToken() ehts should have set 3 keys")
		}
	case <-time.After(time.Second):
		t.Errorf("AccessToken() should have called tg.Generate()")
	}

	select {
	case req := <-mHTTP.wasSet:
		if req.URL.String() != mockUrlStr+"/oauth2/v1/tokens" {
			t.Errorf("AccessToken() should have set URL")
		}
		if req.Method != "POST" {
			t.Errorf("AccessToken() should have set method")
		}
		if req.Header.Get("Authorization") != "clientSecret" {
			t.Errorf("AccessToken() should have set Authorization header")
		}
		if req.Header.Get("X-Authorization") != "generatedPopToken" {
			t.Errorf("AccessToken() should have set X-Authorization header")
		}

		if len(req.Header) != 2 {
			t.Errorf("AccessToken() should have set 2 headers")
		}

		if req.Body != nil {
			t.Errorf("AccessToken() should have no body")
		}
	case <-time.After(time.Second):
		t.Errorf("AccessToken() should have called http.Do()")
	}
}

func TestNewTMobileClient(t *testing.T) {
	cl, err := NewTMobileClient("http://localhost:8080", tmobtokengen.NewMockTokenGenerator{}, time.Second)
	if err != nil {
		t.Errorf("NewTMobileClient() should have succeeded: %v", err)
	}
	if cl == nil {
		t.Errorf("NewTMobileClient() should have returned non-nil")
	}

	cl, err = NewTMobileClient("\thisisnotparsable", nil, 0)
	if err == nil {
		t.Errorf("NewTMobileClient() should have failed: %v", err)
	}
	if cl != nil {
		t.Errorf("NewTMobileClient() should have returned nil")
	}
}

func TestTMobClient_SetAccessToken(t *testing.T) {
	cl := &TMobClient{}
	cl.SetAccessToken("token")
	if cl.accessToken != "Bearer token" {
		t.Errorf("SetAccessToken() should have set access token")
	}
}

type mockHTTPClientSendSMS struct {
	wasSet chan *http.Request
}

func (c *mockHTTPClientSendSMS) Do(req *http.Request) (*http.Response, error) {
	c.wasSet <- req

	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(strings.NewReader(mockSendSMSJsonRes)),
	}, nil
}

var mockSendSMSJsonRes = `{"smsMessageId": "1"}
`

func TestTMobClient_SendSMS(t *testing.T) {
	mtg := &mockTG{wasSet: make(chan tmobtokengen.EHTSMap, 1)}
	mHTTP := &mockHTTPClientSendSMS{wasSet: make(chan *http.Request, 1)}

	cl := &TMobClient{
		client:      mHTTP,
		tg:          mtg,
		baseURL:     mockUrl,
		accessToken: "Bearer token",
	}

	msrs := "{\"iccid\":\"12345678901234567890\",\"messageText\":\"Hello world\"}\n"
	res, err := cl.SendSMS(mockCtx, mockSmsRequest)
	if err != nil {
		t.Errorf("SendSMS() should have succeeded: %v", err)
	}

	if res.SmsMessageID != "1" {
		t.Errorf("SendSMS() should have returned smsMessageId")
	}

	select {
	case ehts := <-mtg.wasSet:
		if ehts["uri"] != "/eitcsr-iotcp-notifications-v2/prd02/iotcp/v2/notifications/sms/messages" {
			t.Errorf("SendSMS() ehts should have set uri")
		}
		if ehts["http-method"] != "POST" {
			t.Errorf("SendSMS() ehts should have set method")
		}
		if ehts["Content-Type"] != "application/json" {
			t.Errorf("SendSMS() ehts should have set Content-Type")
		}

		if ehts["Authorization"] != "Bearer token" {
			t.Errorf("SendSMS() ehts should have set Authorization header")
		}

		if ehts["body"] != msrs {
			t.Errorf("SendSMS() ehts should have set Body")
		}
		if len(ehts) != 5 {
			t.Errorf("SendSMS() ehts should have set 4 keys")
		}
	case <-time.After(time.Second):
		t.Errorf("SendSMS() should have called tg.Generate()")
	}

	select {
	case req := <-mHTTP.wasSet:
		if req.URL.String() != mockUrlStr+"/eitcsr-iotcp-notifications-v2/prd02/iotcp/v2/notifications/sms/messages" {
			t.Errorf("SendSMS() should have set URL")
		}
		if req.Method != "POST" {
			t.Errorf("SendSMS() should have set method")
		}

		if req.Header.Get("Authorization") != "Bearer token" {
			t.Errorf("SendSMS() should have set Authorization header")
		}

		if req.Header.Get("X-Authorization") != "generatedPopToken" {
			t.Errorf("SendSMS() should have set X-Authorization header")
		}

		if req.Header.Get(XAuthOriginator) != "token" {
			t.Errorf("SendSMS() should have set x-auth-originator header")
		}

		if req.Header.Get("Content-Type") != "application/json" {
			t.Errorf("SendSMS() should have set X-Authorization header")
		}

		if len(req.Header) != 4 {
			t.Errorf("SendSMS() should have set 4 headers")
		}

		b, err := io.ReadAll(req.Body)
		if err != nil {
			t.Errorf("SendSMS() should have read body")
		}

		if string(b) != msrs {
			t.Errorf("SendSMS() should have set body")
		}

	case <-time.After(time.Second):
		t.Errorf("SendSMS() should have called http.Do()")
	}
}

type mockHTTPClientDetails struct {
	wasSet chan *http.Request
}

func (c *mockHTTPClientDetails) Do(req *http.Request) (*http.Response, error) {
	c.wasSet <- req

	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(strings.NewReader(mockSmsDetailsJsonRes)),
	}, nil
}

// inited above
var mockSmsDetailsJsonRes string

func TestTMobClient_Details(t *testing.T) {
	mtg := &mockTG{wasSet: make(chan tmobtokengen.EHTSMap, 1)}
	mHTTP := &mockHTTPClientDetails{wasSet: make(chan *http.Request, 1)}

	cl := &TMobClient{
		client:      mHTTP,
		tg:          mtg,
		baseURL:     mockUrl,
		accessToken: "Bearer token",
	}

	ID := "12345678901234567890"

	res, err := cl.Details(mockCtx, ID)
	if err != nil {
		t.Errorf("Details() should have succeeded: %v", err)
	}
	if !reflect.DeepEqual(mockSmsDetailsResponse, res) {
		t.Errorf("Details() got %v, want %v", res, mockSmsDetailsResponse)
	}

	genPath := fmt.Sprintf("/eitcsr-iotcp-notifications-v2/prd02/iotcp/v2/notifications/sms/messages/%s", ID)
	select {
	case ehts := <-mtg.wasSet:
		if ehts["uri"] != genPath {
			t.Errorf("Details() ehts should have set uri")
		}
		if ehts["http-method"] != "GET" {
			t.Errorf("Details() ehts should have set method")
		}

		if ehts["Authorization"] != "Bearer token" {
			t.Errorf("Details() ehts should have set Authorization header")
		}

		if len(ehts) != 3 {
			t.Errorf("Details() ehts should have set 3 keys")
		}
	case <-time.After(time.Second):
		t.Errorf("Details() should have called tg.Generate()")
	}

	select {
	case req := <-mHTTP.wasSet:
		if req.URL.String() != mockUrlStr+genPath {
			t.Errorf("Details() should have set URL")
		}
		if req.Method != "GET" {
			t.Errorf("Details() should have set method")
		}

		if req.Header.Get("Authorization") != "Bearer token" {
			t.Errorf("Details() should have set Authorization header")
		}

		if req.Header.Get("X-Authorization") != "generatedPopToken" {
			t.Errorf("Details() should have set X-Authorization header")
		}

		if req.Header.Get(XAuthOriginator) != "token" {
			t.Errorf("Details() should have set x-auth-originator header")
		}

		if req.Header.Get("Content-Type") != "application/json" {
			t.Errorf("SendSMS() should have set X-Authorization header")
		}

		if len(req.Header) != 4 {
			t.Errorf("Details() should have set 4 headers")
		}

		if req.Body != nil {
			t.Errorf("Details() should have set nil body")
		}
	case <-time.After(time.Second):
		t.Errorf("Details() should have called http.Do()")
	}
}

func TestInitTokenGen(t *testing.T) {
	tg, err := InitTokenGen(mockPKCS8, "client_id", "secret")
	if err != nil {
		t.Errorf("InitTokenGen() error = %v", err)
	}
	if tg == nil {
		t.Errorf("InitTokenGen() tg is nil")
	}

	tg, err = InitTokenGen("/tmp/thisFileDoesntExist", "client_id", "secret")
	if err == nil {
		t.Errorf("InitTokenGen() should have failed")
	}
	if tg != nil {
		t.Errorf("InitTokenGen() should have returned nil")
	}

	tg, err = InitTokenGen(mockPKCS8Fail, "client_id", "secret")
	if err == nil {
		t.Errorf("InitTokenGen() should have failed")
	}
	if tg != nil {
		t.Errorf("InitTokenGen() should have returned nil")
	}
}

type mockHTTPClientCustomAttributes struct {
	wasSet chan *http.Request
}

var mockCustomAttributesRequest = &CustomAtributesRequest{
	ICCID:          "12345678901234567890",
	AccountCustom1: "US",
}
var mockCustomAttributesJsonRes = `{"iccid": "12345678901234567890"}`

func (c *mockHTTPClientCustomAttributes) Do(req *http.Request) (*http.Response, error) {
	c.wasSet <- req

	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(strings.NewReader(mockCustomAttributesJsonRes)),
	}, nil
}

func TestTMobClient_CustomAttributes(t *testing.T) {
	mtg := &mockTG{wasSet: make(chan tmobtokengen.EHTSMap, 1)}
	mHTTP := &mockHTTPClientCustomAttributes{wasSet: make(chan *http.Request, 1)}

	cl := &TMobClient{
		client:      mHTTP,
		tg:          mtg,
		baseURL:     mockUrl,
		accessToken: "Bearer token",
	}

	msrs := "{\"iccid\":\"12345678901234567890\",\"accountCustom1\":\"US\"}\n"
	res, err := cl.CustomAttributes(mockCtx, mockCustomAttributesRequest)
	if err != nil {
		t.Errorf("CustomAttributes() should have succeeded: %v", err)
	}

	if res.ICCID != "12345678901234567890" {
		t.Errorf("CustomAttributes() should have returned smsMessageId")
	}

	select {
	case ehts := <-mtg.wasSet:
		if ehts["uri"] != "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/device-attributes" {
			t.Errorf("CustomAttributes() ehts should have set uri")
		}
		if ehts["http-method"] != "POST" {
			t.Errorf("CustomAttributes() ehts should have set method")
		}
		if ehts["Content-Type"] != "application/json" {
			t.Errorf("CustomAttributes() ehts should have set Content-Type")
		}

		if ehts["Authorization"] != "Bearer token" {
			t.Errorf("CustomAttributes() ehts should have set Authorization header")
		}

		if ehts["body"] != msrs {
			t.Errorf("CustomAttributes() ehts should have set Body")
		}
		if len(ehts) != 5 {
			t.Errorf("CustomAttributes() ehts should have set 4 keys")
		}
	case <-time.After(time.Second):
		t.Errorf("CustomAttributes() should have called tg.Generate()")
	}

	select {
	case req := <-mHTTP.wasSet:
		if req.URL.String() != mockUrlStr+"/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/device-attributes" {
			t.Errorf("CustomAttributes() should have set URL")
		}
		if req.Method != "POST" {
			t.Errorf("CustomAttributes() should have set method")
		}

		if req.Header.Get("Authorization") != "Bearer token" {
			t.Errorf("CustomAttributes() should have set Authorization header")
		}

		if req.Header.Get("X-Authorization") != "generatedPopToken" {
			t.Errorf("CustomAttributes() should have set X-Authorization header")
		}

		if req.Header.Get(XAuthOriginator) != "token" {
			t.Errorf("CustomAttributes() should have set x-auth-originator header")
		}

		if req.Header.Get("Content-Type") != "application/json" {
			t.Errorf("CustomAttributes() should have set X-Authorization header")
		}

		if len(req.Header) != 4 {
			t.Errorf("CustomAttributes() should have set 4 headers")
		}

		b, err := io.ReadAll(req.Body)
		if err != nil {
			t.Errorf("CustomAttributes() should have read body")
		}

		if string(b) != msrs {
			t.Errorf("CustomAttributes() should have set body")
		}

	case <-time.After(time.Second):
		t.Errorf("CustomAttributes() should have called http.Do()")
	}
}

type mockHTTPClientChangeRatePlan struct {
	wasSet chan *http.Request
}

var mockChangeRatePlanRequest = &ChangeRatePlanRequest{
	ICCID:     "12345678901234567890",
	ProductId: "product_1_with_rate_plan_1",
}
var mockChangeRatePlanRequestJsonRes = `{"iccid": "12345678901234567890"}`

func (c *mockHTTPClientChangeRatePlan) Do(req *http.Request) (*http.Response, error) {
	c.wasSet <- req

	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(strings.NewReader(mockChangeRatePlanRequestJsonRes)),
	}, nil
}

func TestTMobClient_ChangeRatePlan(t *testing.T) {
	mtg := &mockTG{wasSet: make(chan tmobtokengen.EHTSMap, 1)}
	mHTTP := &mockHTTPClientChangeRatePlan{wasSet: make(chan *http.Request, 1)}

	cl := &TMobClient{
		client:      mHTTP,
		tg:          mtg,
		baseURL:     mockUrl,
		accessToken: "Bearer token",
	}
	msrs := "{\"iccid\":\"12345678901234567890\",\"productId\":\"product_1_with_rate_plan_1\"}\n"
	res, err := cl.ChangeRatePlan(mockCtx, mockChangeRatePlanRequest)
	if err != nil {
		t.Errorf("ChangeRatePlan() should have succeeded: %v", err)
	}

	if res.ICCID != "12345678901234567890" {
		t.Errorf("ChangeRatePlan() should have returned smsMessageId")
	}

	select {
	case ehts := <-mtg.wasSet:
		if ehts["uri"] != "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/change-rate-plan" {
			t.Errorf("ChangeRatePlan() ehts should have set uri")
		}
		if ehts["http-method"] != "POST" {
			t.Errorf("ChangeRatePlan() ehts should have set method")
		}
		if ehts["Content-Type"] != "application/json" {
			t.Errorf("ChangeRatePlan() ehts should have set Content-Type")
		}

		if ehts["Authorization"] != "Bearer token" {
			t.Errorf("ChangeRatePlan() ehts should have set Authorization header")
		}

		if ehts["body"] != msrs {
			t.Errorf("ChangeRatePlan() ehts should have set Body")
		}
		if len(ehts) != 5 {
			t.Errorf("ChangeRatePlan() ehts should have set 4 keys")
		}
	case <-time.After(time.Second):
		t.Errorf("ChangeRatePlan() should have called tg.Generate()")
	}

	select {
	case req := <-mHTTP.wasSet:
		if req.URL.String() != mockUrlStr+"/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/change-rate-plan" {
			t.Errorf("ChangeRatePlan() should have set URL")
		}
		if req.Method != "POST" {
			t.Errorf("ChangeRatePlan() should have set method")
		}

		if req.Header.Get("Authorization") != "Bearer token" {
			t.Errorf("ChangeRatePlan() should have set Authorization header")
		}

		if req.Header.Get("X-Authorization") != "generatedPopToken" {
			t.Errorf("ChangeRatePlan() should have set X-Authorization header")
		}

		if req.Header.Get(XAuthOriginator) != "token" {
			t.Errorf("ChangeRatePlan() should have set x-auth-originator header")
		}

		if req.Header.Get("Content-Type") != "application/json" {
			t.Errorf("ChangeRatePlan() should have set X-Authorization header")
		}

		if len(req.Header) != 4 {
			t.Errorf("ChangeRatePlan() should have set 4 headers")
		}

		b, err := io.ReadAll(req.Body)
		if err != nil {
			t.Errorf("ChangeRatePlan() should have read body")
		}

		if string(b) != msrs {
			t.Errorf("ChangeRatePlan() should have set body")
		}

	case <-time.After(time.Second):
		t.Errorf("ChangeRatePlan() should have called http.Do()")
	}
}

type mockHTTPClientGetProducts struct {
	wasSet chan *http.Request
}

var mockGetProductsRequest = &sms.GetAvailableProductsRequest{
	AccountId:             "fisker_tmobile_1",
	ProductType:           []string{"RATEPLAN"},
	ProductClassification: []string{"IOTCONNECTIVITY"},
}

var mockGetProductsJsonRes = `[{"id": "1", "productId": "product_2","shortDescription": "short", "longDescription":"long", "status": "Published", "effectiveDate": "2021-02-17T19:49:00+00:00", "expirationDate": "", "ratePlan": {}}]`

func (c *mockHTTPClientGetProducts) Do(req *http.Request) (*http.Response, error) {
	c.wasSet <- req

	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(strings.NewReader(mockGetProductsJsonRes)),
	}, nil
}

func TestTMobClient_GetProducts(t *testing.T) {
	mtg := &mockTG{wasSet: make(chan tmobtokengen.EHTSMap, 1)}
	mHTTP := &mockHTTPClientGetProducts{wasSet: make(chan *http.Request, 1)}

	cl := &TMobClient{
		client:      mHTTP,
		tg:          mtg,
		baseURL:     mockUrl,
		accessToken: "Bearer token",
	}
	msrs := "{\"accountId\":\"fisker_tmobile_1\",\"productType\":[\"RATEPLAN\"],\"productClassification\":[\"IOTCONNECTIVITY\"]}\n"
	res, err := cl.GetProducts(mockCtx, mockGetProductsRequest)
	if err != nil {
		t.Errorf("GetProducts() should have succeeded: %v", err)
	}

	if res.AvailableProducts[0].ProductId != "product_2" {
		t.Errorf("GetProducts() should have returned correct products")
	}

	select {
	case ehts := <-mtg.wasSet:
		if ehts["uri"] != "/eitcsr-iot-product-service-v1/prd02/iotcp/v1/iot-product-service/products/query" {
			t.Errorf("GetProducts() ehts should have set uri")
		}
		if ehts["http-method"] != "POST" {
			t.Errorf("GetProducts() ehts should have set method")
		}
		if ehts["Content-Type"] != "application/json" {
			t.Errorf("GetProducts() ehts should have set Content-Type")
		}

		if ehts["Authorization"] != "Bearer token" {
			t.Errorf("GetProducts() ehts should have set Authorization header")
		}
		if ehts["body"] != msrs {
			t.Errorf("GetProducts() ehts should have set Body")
		}
		if len(ehts) != 5 {
			t.Errorf("GetProducts() ehts should have set 4 keys")
		}
	case <-time.After(time.Second):
		t.Errorf("GetProducts() should have called tg.Generate()")
	}

	select {
	case req := <-mHTTP.wasSet:
		if req.URL.String() != mockUrlStr+"/eitcsr-iot-product-service-v1/prd02/iotcp/v1/iot-product-service/products/query" {
			t.Errorf("GetProducts() should have set URL")
		}
		if req.Method != "POST" {
			t.Errorf("GetProducts() should have set method")
		}

		if req.Header.Get("Authorization") != "Bearer token" {
			t.Errorf("GetProducts() should have set Authorization header")
		}

		if req.Header.Get("X-Authorization") != "generatedPopToken" {
			t.Errorf("GetProducts() should have set X-Authorization header")
		}
		if req.Header.Get(XAuthOriginator) != "token" {
			t.Errorf("GetProducts() should have set x-auth-originator header")
		}

		if req.Header.Get("Content-Type") != "application/json" {
			t.Errorf("GetProducts() should have set X-Authorization header")
		}

		if len(req.Header) != 4 {
			t.Errorf("GetProducts() should have set 4 headers")
		}

		b, err := io.ReadAll(req.Body)
		if err != nil {
			t.Errorf("GetProducts() should have read body")
		}

		if string(b) != msrs {
			t.Errorf("GetProducts() should have set body")
		}

	case <-time.After(time.Second):
		t.Errorf("GetProducts() should have called http.Do()")
	}
}

type mockHTTPClientDeviceDetails struct {
	wasSet chan *http.Request
}

var mockDeviceDetailsRequest = &DeviceDetailsRequest{
	ICCID: "1234567890",
}

var mockDeviceDetailsJsonRes = `{"iccid": "1234567890", "ratePlan": "plan_1", "accountId": "account_1", "accountCustom1": "US", "status": "published"}`

func (c *mockHTTPClientDeviceDetails) Do(req *http.Request) (*http.Response, error) {
	c.wasSet <- req

	return &http.Response{
		StatusCode: 200,
		Body:       io.NopCloser(strings.NewReader(mockDeviceDetailsJsonRes)),
	}, nil
}

func TestTMobClient_DeviceDetails(t *testing.T) {
	mtg := &mockTG{wasSet: make(chan tmobtokengen.EHTSMap, 1)}
	mHTTP := &mockHTTPClientDeviceDetails{wasSet: make(chan *http.Request, 1)}

	cl := &TMobClient{
		client:      mHTTP,
		tg:          mtg,
		baseURL:     mockUrl,
		accessToken: "Bearer token",
	}
	msrs := "{\"iccid\":\"1234567890\"}\n"
	res, err := cl.DeviceDetails(mockCtx, mockDeviceDetailsRequest)
	if err != nil {
		t.Errorf("DeviceDetails() should have succeeded: %v", err)
	}

	if res.ICCID != "1234567890" {
		t.Errorf("DeviceDetails() should have returned correct products")
	}

	select {
	case ehts := <-mtg.wasSet:
		if ehts["uri"] != "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/details" {
			t.Errorf("DeviceDetails() ehts should have set uri")
		}
		if ehts["http-method"] != "POST" {
			t.Errorf("DeviceDetails() ehts should have set method")
		}
		if ehts["Content-Type"] != "application/json" {
			t.Errorf("DeviceDetails() ehts should have set Content-Type")
		}

		if ehts["Authorization"] != "Bearer token" {
			t.Errorf("DeviceDetails() ehts should have set Authorization header")
		}
		if ehts["body"] != msrs {
			t.Errorf("DeviceDetails() ehts should have set Body")
		}
		if len(ehts) != 5 {
			t.Errorf("DeviceDetails() ehts should have set 4 keys")
		}
	case <-time.After(time.Second):
		t.Errorf("DeviceDetails() should have called tg.Generate()")
	}

	select {
	case req := <-mHTTP.wasSet:
		if req.URL.String() != mockUrlStr+"/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/details" {
			t.Errorf("DeviceDetails() should have set URL")
		}
		if req.Method != "POST" {
			t.Errorf("DeviceDetails() should have set method")
		}

		if req.Header.Get("Authorization") != "Bearer token" {
			t.Errorf("DeviceDetails() should have set Authorization header")
		}

		if req.Header.Get("X-Authorization") != "generatedPopToken" {
			t.Errorf("DeviceDetails() should have set X-Authorization header")
		}

		if req.Header.Get(XAuthOriginator) != "token" {
			t.Errorf("DeviceDetails() should have set x-auth-originator header")
		}

		if req.Header.Get("Content-Type") != "application/json" {
			t.Errorf("DeviceDetails() should have set X-Authorization header")
		}

		if len(req.Header) != 4 {
			t.Errorf("DeviceDetails() should have set 4 headers")
		}

		b, err := io.ReadAll(req.Body)
		if err != nil {
			t.Errorf("DeviceDetails() should have read body")
		}

		if string(b) != msrs {
			t.Errorf("DeviceDetails() should have set body")
		}

	case <-time.After(time.Second):
		t.Errorf("DeviceDetails() should have called http.Do()")
	}
}
