package mgmt

import (
	"encoding/base64"
	"encoding/json"
	"net/http"
	"strings"

	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/errs"
)

type OffsetPagination struct {
	Page      int
	PageSize  int
	ClusterID string
}

type offsetPageToken struct {
	OrgID     string `json:"org_id"`
	Page      int    `json:"page"`
	PageSize  int    `json:"page_size"`
	ClusterID string `json:"cluster_id,omitempty"`
}

func ResolveOffsetPagination(orgID string, opts ListClustersOptions) (OffsetPagination, error) {
	orgID = strings.TrimSpace(orgID)
	clusterID := strings.TrimSpace(opts.ClusterID)
	if orgID == "" {
		return OffsetPagination{}, errs.APIErrorf(http.StatusBadRequest, "tidbcloud_org_id is required")
	}
	if opts.PageSize <= 0 {
		return OffsetPagination{}, errs.APIErrorf(http.StatusBadRequest, "page_size must be positive")
	}

	if strings.TrimSpace(opts.PageToken) == "" {
		return OffsetPagination{
			Page:      1,
			PageSize:  opts.PageSize,
			ClusterID: clusterID,
		}, nil
	}

	token, err := decodeOffsetPageToken(opts.PageToken)
	if err != nil {
		return OffsetPagination{}, err
	}
	if token.OrgID != orgID || token.PageSize != opts.PageSize || token.ClusterID != clusterID {
		return OffsetPagination{}, errs.APIErrorf(http.StatusBadRequest, "page_token does not match current org_id, page_size, or cluster_id")
	}
	if token.Page <= 0 {
		return OffsetPagination{}, errs.APIErrorf(http.StatusBadRequest, "page_token contains invalid page")
	}

	return OffsetPagination{
		Page:      token.Page,
		PageSize:  token.PageSize,
		ClusterID: token.ClusterID,
	}, nil
}

func EncodeNextOffsetPageToken(orgID string, opts ListClustersOptions, currentPage int, hasMore bool) (string, error) {
	if !hasMore {
		return "", nil
	}
	if currentPage <= 0 {
		return "", errs.APIErrorf(http.StatusBadRequest, "current page must be positive")
	}

	token := offsetPageToken{
		OrgID:     strings.TrimSpace(orgID),
		Page:      currentPage + 1,
		PageSize:  opts.PageSize,
		ClusterID: strings.TrimSpace(opts.ClusterID),
	}
	data, err := json.Marshal(token)
	if err != nil {
		return "", err
	}
	return base64.RawURLEncoding.EncodeToString(data), nil
}

func decodeOffsetPageToken(raw string) (offsetPageToken, error) {
	data, err := base64.RawURLEncoding.DecodeString(raw)
	if err != nil {
		return offsetPageToken{}, errs.APIErrorNew(http.StatusBadRequest, err)
	}

	var token offsetPageToken
	if err := json.Unmarshal(data, &token); err != nil {
		return offsetPageToken{}, errs.APIErrorNew(http.StatusBadRequest, err)
	}
	return token, nil
}
