package tmobile

import (
	"math/rand"
	"strconv"
	"strings"
	"testing"
	"time"

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

func TestSendSMSRequest_ExpireIfNotDelivered(t *testing.T) {
	t.Skip()
	req := &SendSMSRequest{}

	expectedExpr := req.ExpireIfNotDelivered()

	if *req.TPVP != "0" || expectedExpr != minAwait {
		t.Errorf("expected tpvp to be %s, got %s", tpvpUnit, *req.TPVP)
		t.Errorf("expected expire to be %s, got %s", tpvpUnit, expectedExpr)
	}

	nan := "not-a-number"
	req.TPVP = &nan
	expectedExpr = req.ExpireIfNotDelivered()
	if *req.TPVP != "0" || expectedExpr != minAwait {
		t.Errorf("expected tpvp to be %s, got %s", tpvpUnit, *req.TPVP)
		t.Errorf("expected expire to be %s, got %s", tpvpUnit, expectedExpr)
	}

	moreThan255 := "256"
	req.TPVP = &moreThan255
	expectedExpr = req.ExpireIfNotDelivered()
	if *req.TPVP != "255" || expectedExpr != tpvpUnit*255 {
		t.Errorf("expected tpvp to be %s, got %s", tpvpUnit*255, *req.TPVP)
		t.Errorf("expected expire to be %s, got %s", tpvpUnit*255, expectedExpr)
	}

	lessThan0 := "-1"
	req.TPVP = &lessThan0
	expectedExpr = req.ExpireIfNotDelivered()
	if *req.TPVP != "0" || expectedExpr != minAwait {
		t.Errorf("expected tpvp to be %s, got %s", tpvpUnit, *req.TPVP)
		t.Errorf("expected expire to be %s, got %s", tpvpUnit, expectedExpr)
	}

	rand.Seed(time.Now().Unix())
	randInt := rand.Intn(254) + 1
	ris := strconv.Itoa(randInt)
	req.TPVP = &ris
	wantExpire := time.Duration(randInt) * tpvpUnit

	expectedExpr = req.ExpireIfNotDelivered()
	if *req.TPVP != ris || expectedExpr != wantExpire {
		t.Errorf("expected tpvp to be %s, got %s", ris, *req.TPVP)
		t.Errorf("expected expire to be %s, got %s", wantExpire, expectedExpr)
	}
}

var mockProtoSmsRequest = &sms.SendSMSRequest{
	ICCID:       "12345678901234567890",
	MessageText: "Hello World",
}

var mockProtoSmsRequestWithTrailingF = &sms.SendSMSRequest{
	ICCID:       "12345678901234567890F",
	MessageText: "Hello World",
}

func TestSendSMSRequest_FromProtobufWithTralingFAndWithout(t *testing.T) {
	iccid := "12345678901234567890"
	protoReq := mockProtoSmsRequestWithTrailingF

	req := &SendSMSRequest{}
	req.FromProtobuf(protoReq)

	if strings.HasSuffix(strings.ToLower(req.ICCID), "f") {
		t.Errorf("expected ICCID not to have trailing F, got %s", req.ICCID)
	}

	if req.ICCID != iccid {
		t.Errorf("expected ICCID to be %s, got %s", iccid, req.ICCID)
	}

	protoReq = mockProtoSmsRequest

	req = &SendSMSRequest{}
	req.FromProtobuf(protoReq)

	if req.ICCID != iccid {
		t.Errorf("expected ICCID to be %s, got %s", iccid, req.ICCID)
	}
}

func TestSendSMSRequest_FromProtobuf(t *testing.T) {
	encoding := sms.SendSMSRequest_LITERAL
	dataCoding := sms.SendSMSRequest_FOUR
	tpvp := "1"

	mockProtoSmsRequest.MessageEncoding = &encoding
	mockProtoSmsRequest.DataCoding = &dataCoding
	mockProtoSmsRequest.Tpvp = &tpvp

	protoReq := mockProtoSmsRequest

	req := &SendSMSRequest{}
	req.FromProtobuf(protoReq)

	if req.ICCID != protoReq.ICCID {
		t.Errorf("expected ICCID to be %s, got %s", protoReq.ICCID, req.ICCID)
	}

	if req.MessageText != protoReq.MessageText {
		t.Errorf("expected MessageText to be %s, got %s", protoReq.MessageText, req.MessageText)
	}

	if *req.MessageEncoding != protoReq.MessageEncoding.Enum().String() {
		t.Errorf("expected MessageEncoding to be %s, got %s", protoReq.MessageEncoding.Enum().String(), *req.MessageEncoding)
	}

	if *req.DataCoding != strconv.Itoa(int(protoReq.DataCoding.Enum().Number())) {
		t.Errorf("expected DataCoding to be %d, got %s", protoReq.DataCoding.Enum().Number(), *req.DataCoding)
	}

	if *req.TPVP != tpvp {
		t.Errorf("expected TPVP to be %s, got %s", tpvp, *req.TPVP)
	}
}

var smsStatuses = map[string]struct{}{
	string(Received):      {},
	string(Cancelled):     {},
	string(CancelFailed):  {},
	string(CancelPending): {},
	string(Delivered):     {},
	string(Pending):       {},
	string(Failed):        {},
	string(Unknown):       {},
}

var mockSmsDetailsResponse = &SMSDetailsResponse{
	SmsMsgID:     "12345678901234567890",
	Status:       "some status",
	MessageText:  "Hello World",
	SenderLogin:  "login",
	SentTo:       "someone",
	SentFrom:     "someone else",
	MsgType:      "type",
	DateSent:     "date sent",
	DateModified: "date modified",
	ICCID:        "12345678901234567890",
}

func TestSMSDetailsResponse_AsProtobuf(t *testing.T) {
	req := mockSmsDetailsResponse

	protoReq := req.ToProtobuf()

	if protoReq.ICCID != req.ICCID {
		t.Errorf("expected ICCID to be %s, got %s", req.ICCID, protoReq.ICCID)
	}

	if protoReq.SmsMsgID != req.SmsMsgID {
		t.Errorf("expected SmsMsgID to be %s, got %s", req.SmsMsgID, protoReq.SmsMsgID)
	}

	if protoStatus, reqStatus := protoReq.Status.Enum().String(), string(req.Status); protoStatus != reqStatus {
		if _, ok := smsStatuses[reqStatus]; ok || protoStatus != "Unknown" {
			t.Errorf("expected Status to be %s, got %s", req.Status, protoReq.Status)
		}
	}

	if protoReq.MessageText != req.MessageText {
		t.Errorf("expected MessageText to be %s, got %s", req.MessageText, protoReq.MessageText)
	}

	if protoReq.SenderLogin != req.SenderLogin {
		t.Errorf("expected SenderLogin to be %s, got %s", req.SenderLogin, protoReq.SenderLogin)
	}

	if protoReq.SentTo != req.SentTo {
		t.Errorf("expected SentTo to be %s, got %s", req.SentTo, protoReq.SentTo)
	}

	if protoReq.SentFrom != req.SentFrom {
		t.Errorf("expected SentFrom to be %s, got %s", req.SentFrom, protoReq.SentFrom)
	}

	if protoReq.MsgType != req.MsgType {
		t.Errorf("expected MsgType to be %s, got %s", req.MsgType, protoReq.MsgType)
	}

	if protoReq.DateSent != req.DateSent {
		t.Errorf("expected DateSent to be %s, got %s", req.DateSent, protoReq.DateSent)
	}

	if protoReq.DateModified != req.DateModified {
		t.Errorf("expected DateModified to be %s, got %s", req.DateModified, protoReq.DateModified)
	}
}
