package exec

import (
	"context"
	"net/url"
	"strconv"
	"strings"

	"github.com/tidbcloud/AgentTeam/desktop/internal/wire/apiclient"
)

type roleRemote struct {
	client  *apiclient.Client
	read    remoteReadTransport
	receipt requestReceiptTransport
}

func (remote roleRemote) readTransport() remoteReadTransport {
	transport := remote.read
	transport.client = remote.client
	return transport
}

func (remote roleRemote) receiptTransport() requestReceiptTransport {
	transport := remote.receipt
	transport.client = remote.client
	return transport
}

func (remote roleRemote) list(ctx context.Context, input roleListRequest) (roleListResult, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return roleListResult{}, err
	}
	values := url.Values{}
	if value := strings.TrimSpace(input.View); value != "" {
		values.Set("view", value)
	}
	if value := strings.TrimSpace(input.Query); value != "" {
		values.Set("q", value)
	}
	if input.Limit != 0 {
		values.Set("limit", strconv.Itoa(input.Limit))
	}
	if value := strings.TrimSpace(input.Cursor); value != "" {
		values.Set("cursor", value)
	}
	path := remote.client.AgentRuntimePath("/roles")
	if encoded := values.Encode(); encoded != "" {
		path += "?" + encoded
	}
	var result roleListResult
	err := remote.readTransport().get(ctx, path, &result)
	return result, err
}

func (remote roleRemote) get(ctx context.Context, input roleGetRequest) (roleGetResult, error) {
	result, err := rolePost(ctx, remote, "/roles/get", input, roleGetResult{})
	return result, err
}

func (remote roleRemote) requestGet(ctx context.Context, input roleRequestGetRequest) (roleRequestGetResult, error) {
	result, err := rolePost(ctx, remote, "/roles/request-get", input, roleRequestGetResult{})
	return result, err
}

func (remote roleRemote) create(ctx context.Context, input roleCreateRequest) (roleRequestResponse, error) {
	result, err := rolePost(ctx, remote, "/roles/create", input, roleRequestResponse{})
	return result, err
}

func (remote roleRemote) update(ctx context.Context, input roleUpdateRequest) (roleRequestResponse, error) {
	result, err := rolePost(ctx, remote, "/roles/update", input, roleRequestResponse{})
	return result, err
}

func (remote roleRemote) delete(ctx context.Context, input roleDeleteRequest) (roleRequestResponse, error) {
	result, err := rolePost(ctx, remote, "/roles/delete", input, roleRequestResponse{})
	return result, err
}

func (remote roleRemote) apply(ctx context.Context, input roleApplyRequest) (roleRequestResponse, error) {
	result, err := rolePost(ctx, remote, "/roles/apply", input, roleRequestResponse{})
	return result, err
}

func rolePost[T any](ctx context.Context, remote roleRemote, suffix string, input any, zero T) (T, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return zero, err
	}
	result := zero
	if key := requestIDFromPayload(input); key != "" {
		err := remote.receiptTransport().post(ctx, remote.client.AgentRuntimePath(suffix), input, &result, replayHeaders(key))
		return result, err
	}
	err := remote.readTransport().post(ctx, remote.client.AgentRuntimePath(suffix), input, &result)
	return result, err
}
