package call

import (
	"fmt"
	"strings"

	"github.com/tidbcloud/escalation-base/feishu_messager_v2/api"
	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/infra/errs"
	twilio "github.com/twilio/twilio-go"
	twilioApi "github.com/twilio/twilio-go/rest/api/v2010"
)

const voiceMessage = "This is an urgent Lark notification. Please check your Lark messages as soon as possible."

type client struct {
	raw     *twilio.RestClient
	callers []CallerNumber
}

func New(raw *twilio.RestClient, callers []CallerNumber) Call {
	return &client{
		raw:     raw,
		callers: callers,
	}
}

func (cli *client) SingleCall(callNumber string) error {
	callFrom, err := cli.selectCallerNumber(callNumber)
	if err != nil {
		return err
	}

	params := &twilioApi.CreateCallParams{}
	params.SetTo(callNumber)
	params.SetFrom(callFrom)
	params.SetTwiml(fmt.Sprintf(
		"<Response><Say language=\"en-US\">%s</Say></Response>",
		voiceMessage,
	))

	_, err = cli.raw.Api.CreateCall(params)
	if err != nil {
		return errs.APIErrorNew(api.ErrCodeUnavailable, err)
	}
	return nil
}

func (cli *client) selectCallerNumber(callNumber string) (string, error) {
	var (
		fallback    string
		bestMatch   string
		bestMatchLn int
	)

	for _, caller := range cli.callers {
		if caller.Prefix == "+1" {
			fallback = caller.Number
		}
		if strings.HasPrefix(callNumber, caller.Prefix) && len(caller.Prefix) > bestMatchLn {
			bestMatch = caller.Number
			bestMatchLn = len(caller.Prefix)
		}
	}

	if bestMatch != "" {
		return bestMatch, nil
	}
	if fallback != "" {
		return fallback, nil
	}

	return "", errs.APIErrorf(api.ErrCodeInvalidArgument, "no twilio caller configured for number prefix: %s", callNumber)
}
