package netns

import (
	"context"
	"fmt"

	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/client"
)

type NetNS interface {
	Do(fn func() error) error
	Close() error
}

type Runtime interface {
	GetSandboxNetNS(podID string) (NetNS, error)
}

type dockerClient struct {
	cli *client.Client
}

func NewDockerRuntime() (Runtime, error) {
	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
	if err != nil {
		return nil, fmt.Errorf("can't new docker client: %w", err)
	}
	return &dockerClient{
		cli: cli,
	}, nil
}

func (c *dockerClient) GetSandboxNetNS(podID string) (NetNS, error) {
	ctx := context.Background()
	cs, err := c.cli.ContainerList(ctx, container.ListOptions{
		Filters: filters.NewArgs(
			filters.Arg("label", "io.kubernetes.pod.uid="+podID),
			filters.Arg("label", "io.kubernetes.docker.type=podsandbox"),
		),
	})
	if err != nil {
		return nil, err
	}

	if len(cs) != 1 {
		return nil, fmt.Errorf("too many podsandbox with uid %s, expected is 1, actual %v", podID, len(cs))
	}

	detail, err := c.cli.ContainerInspect(ctx, cs[0].ID)
	if err != nil {
		return nil, err
	}

	path := detail.NetworkSettings.SandboxKey

	return NewFromPath(path)
}
