package serverlesscli

import (
	"context"
	"fmt"
	"time"

	"github.com/tidbcloud/serverless-service/idl/pbgen/proto/rpc"
	"github.com/tidbcloud/serverless-service/idl/pbgen/proto/serverless"
	"go.buf.build/protocolbuffers/go/linuxgit/tidbcloud/base"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

type Client struct {
	billingCli serverless.ServerlessBillingServiceClient
	branchCli  rpc.BranchServiceClient
}

func NewClient(addr string) (*Client, error) {
	c := &Client{}

	opts := []grpc.DialOption{
		grpc.WithTransportCredentials(insecure.NewCredentials()), // don't support TLS connection yet
	}
	serverlessConn, err := grpc.NewClient(addr, opts...)
	if err != nil {
		return nil, fmt.Errorf("dial serverless-service %s failed: %s", addr, err)
	}
	c.billingCli = serverless.NewServerlessBillingServiceClient(serverlessConn)
	c.branchCli = rpc.NewBranchServiceClient(serverlessConn)

	return c, nil
}

func (c *Client) GetSpendLimitDetails(ctx context.Context, orgID, clusterID uint64) (*serverless.GetSpendLimitDetailsResp, error) {
	resp, err := c.billingCli.GetSpendLimitDetails(ctx, &serverless.GetSpendLimitDetailsReq{
		OrgId:     orgID,
		ClusterId: clusterID,
	})
	if err != nil {
		return nil, err
	}
	if err := Err(err, resp.BaseResp); err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *Client) ListBranches(ctx context.Context, clusterID uint64) (*rpc.ListBranchesResp, error) {
	t := true
	resp, err := c.branchCli.ListBranches(ctx, &rpc.ListBranchesReq{
		ClusterId: clusterID,
		Filter: &rpc.BranchFilter{
			IncludeDeleted: &t,
		},
	})
	if err != nil {
		return nil, err
	}
	if err := Err(err, resp.BaseResp); err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *Client) GetBranch(clusterID uint64, branchID string) (*rpc.FullBranch, error) {
	ctx, f := context.WithTimeout(context.Background(), 15*time.Second)
	defer f()
	resp, err := c.branchCli.GetBranch(ctx, &rpc.GetBranchReq{
		ClusterId: clusterID,
		BranchId:  branchID,
	})
	if err != nil {
		return nil, err
	}
	if err := Err(err, resp.BaseResp); err != nil {
		return nil, err
	}
	return resp.GetBranch(), nil
}

func Err(err error, resp *base.BaseResp) error {
	if err != nil {
		return err
	}
	if resp == nil {
		return fmt.Errorf("base resp is nil")
	}
	if resp.ErrCode != 0 {
		return fmt.Errorf("serverless service base resp error: %s", resp.ErrMsg)
	}

	return nil
}
