package exec

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

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

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

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

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

func (remote channelRemote) list(ctx context.Context, input channelListInput) (channelListOutput, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return channelListOutput{}, err
	}
	values := url.Values{}
	if input.Limit != 0 {
		values.Set("limit", strconv.Itoa(input.Limit))
	}
	if cursor := strings.TrimSpace(input.Cursor); cursor != "" {
		values.Set("cursor", cursor)
	}
	path := remote.client.AgentRuntimePath("/channels")
	if encoded := values.Encode(); encoded != "" {
		path += "?" + encoded
	}
	var result channelListOutput
	return result, remote.readTransport().get(ctx, path, &result)
}

func (remote channelRemote) get(ctx context.Context, channelID string) (channelGetOutput, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return channelGetOutput{}, err
	}
	channelID = strings.TrimSpace(channelID)
	if channelID == "" {
		return channelGetOutput{}, fmt.Errorf("channel get requires a channel id")
	}
	var result channelGetOutput
	err := remote.readTransport().post(
		ctx,
		remote.client.AgentRuntimePath("/channels/get"),
		map[string]string{"channelId": channelID},
		&result,
	)
	return result, err
}

func (remote channelRemote) members(ctx context.Context, input channelMembersInput) (channelMembersOutput, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return channelMembersOutput{}, err
	}
	input.ChannelID = strings.TrimSpace(input.ChannelID)
	input.Cursor = strings.TrimSpace(input.Cursor)
	channelID := input.ChannelID
	if channelID == "" {
		return channelMembersOutput{}, fmt.Errorf("channel members requires a channel id")
	}
	var result channelMembersOutput
	err := remote.readTransport().post(
		ctx,
		remote.client.AgentRuntimePath("/channels/members"),
		input,
		&result,
	)
	return result, err
}

func (remote channelRemote) create(ctx context.Context, request channelCreateRequest) (channelCreateOutput, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return channelCreateOutput{}, err
	}
	var result channelCreateOutput
	err := remote.receiptTransport().post(ctx, remote.client.AgentRuntimePath("/channels/create"), request, &result, nil)
	return result, err
}

func (remote channelRemote) update(ctx context.Context, _ string, request channelUpdateRequest) (channelUpdateOutput, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return channelUpdateOutput{}, err
	}
	var result channelUpdateOutput
	err := remote.receiptTransport().post(ctx, remote.client.AgentRuntimePath("/channels/update"), request, &result, nil)
	return result, err
}

func (remote channelRemote) agentAdd(ctx context.Context, _ string, request channelAgentMutationRequest) (channelAgentMutationOutput, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return channelAgentMutationOutput{}, err
	}
	var result channelAgentMutationOutput
	err := remote.receiptTransport().post(ctx, remote.client.AgentRuntimePath("/channels/agent-add"), request, &result, nil)
	return result, err
}

func (remote channelRemote) agentRemove(ctx context.Context, _ string, request channelAgentMutationRequest) (channelAgentMutationOutput, error) {
	if err := requireRuntimeClient(remote.client); err != nil {
		return channelAgentMutationOutput{}, err
	}
	var result channelAgentMutationOutput
	err := remote.receiptTransport().post(ctx, remote.client.AgentRuntimePath("/channels/agent-remove"), request, &result, nil)
	return result, err
}
