package environment

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

	"github.com/docker/docker/api/types"
	volumetypes "github.com/docker/docker/api/types/volume"
	"github.com/docker/docker/integration-cli/request"
	icmd "github.com/docker/docker/pkg/testutil/cmd"
)

type testingT interface {
	logT
	Fatalf(string, ...interface{})
}

type logT interface {
	Logf(string, ...interface{})
}

// Clean the environment, preserving protected objects (images, containers, ...)
// and removing everything else. It's meant to run after any tests so that they don't
// depend on each others.
func (e *Execution) Clean(t testingT, dockerBinary string) {
	if (e.DaemonPlatform() != "windows") || (e.DaemonPlatform() == "windows" && e.Isolation() == "hyperv") {
		unpauseAllContainers(t, dockerBinary)
	}
	deleteAllContainers(t, dockerBinary)
	deleteAllImages(t, dockerBinary, e.protectedElements.images)
	deleteAllVolumes(t, dockerBinary)
	deleteAllNetworks(t, dockerBinary, e.DaemonPlatform())
	if e.DaemonPlatform() == "linux" {
		deleteAllPlugins(t, dockerBinary)
	}
}

func unpauseAllContainers(t testingT, dockerBinary string) {
	containers := getPausedContainers(t, dockerBinary)
	if len(containers) > 0 {
		icmd.RunCommand(dockerBinary, append([]string{"unpause"}, containers...)...).Assert(t, icmd.Success)
	}
}

func getPausedContainers(t testingT, dockerBinary string) []string {
	result := icmd.RunCommand(dockerBinary, "ps", "-f", "status=paused", "-q", "-a")
	result.Assert(t, icmd.Success)
	return strings.Fields(result.Combined())
}

func deleteAllContainers(t testingT, dockerBinary string) {
	containers := getAllContainers(t, dockerBinary)
	if len(containers) > 0 {
		result := icmd.RunCommand(dockerBinary, append([]string{"rm", "-fv"}, containers...)...)
		if result.Error != nil {
			// If the error is "No such container: ..." this means the container doesn't exists anymore,
			// we can safely ignore that one.
			if strings.Contains(result.Stderr(), "No such container") {
				return
			}
			t.Fatalf("error removing containers %v : %v (%s)", containers, result.Error, result.Combined())
		}
	}
}

func getAllContainers(t testingT, dockerBinary string) []string {
	result := icmd.RunCommand(dockerBinary, "ps", "-q", "-a")
	result.Assert(t, icmd.Success)
	return strings.Fields(result.Combined())
}

func deleteAllImages(t testingT, dockerBinary string, protectedImages map[string]struct{}) {
	result := icmd.RunCommand(dockerBinary, "images", "--digests")
	result.Assert(t, icmd.Success)
	lines := strings.Split(string(result.Combined()), "\n")[1:]
	imgMap := map[string]struct{}{}
	for _, l := range lines {
		if l == "" {
			continue
		}
		fields := strings.Fields(l)
		imgTag := fields[0] + ":" + fields[1]
		if _, ok := protectedImages[imgTag]; !ok {
			if fields[0] == "<none>" || fields[1] == "<none>" {
				if fields[2] != "<none>" {
					imgMap[fields[0]+"@"+fields[2]] = struct{}{}
				} else {
					imgMap[fields[3]] = struct{}{}
				}
				// continue
			} else {
				imgMap[imgTag] = struct{}{}
			}
		}
	}
	if len(imgMap) != 0 {
		imgs := make([]string, 0, len(imgMap))
		for k := range imgMap {
			imgs = append(imgs, k)
		}
		icmd.RunCommand(dockerBinary, append([]string{"rmi", "-f"}, imgs...)...).Assert(t, icmd.Success)
	}
}

func deleteAllVolumes(t testingT, dockerBinary string) {
	volumes, err := getAllVolumes()
	if err != nil {
		t.Fatalf("%v", err)
	}
	var errs []string
	for _, v := range volumes {
		status, b, err := request.SockRequest("DELETE", "/volumes/"+v.Name, nil, request.DaemonHost())
		if err != nil {
			errs = append(errs, err.Error())
			continue
		}
		if status != http.StatusNoContent {
			errs = append(errs, fmt.Sprintf("error deleting volume %s: %s", v.Name, string(b)))
		}
	}
	if len(errs) > 0 {
		t.Fatalf("%v", strings.Join(errs, "\n"))
	}
}

func getAllVolumes() ([]*types.Volume, error) {
	var volumes volumetypes.VolumesListOKBody
	_, b, err := request.SockRequest("GET", "/volumes", nil, request.DaemonHost())
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(b, &volumes); err != nil {
		return nil, err
	}
	return volumes.Volumes, nil
}

func deleteAllNetworks(t testingT, dockerBinary string, daemonPlatform string) {
	networks, err := getAllNetworks()
	if err != nil {
		t.Fatalf("%v", err)
	}
	var errs []string
	for _, n := range networks {
		if n.Name == "bridge" || n.Name == "none" || n.Name == "host" {
			continue
		}
		if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" {
			// nat is a pre-defined network on Windows and cannot be removed
			continue
		}
		status, b, err := request.SockRequest("DELETE", "/networks/"+n.Name, nil, request.DaemonHost())
		if err != nil {
			errs = append(errs, err.Error())
			continue
		}
		if status != http.StatusNoContent {
			errs = append(errs, fmt.Sprintf("error deleting network %s: %s", n.Name, string(b)))
		}
	}
	if len(errs) > 0 {
		t.Fatalf("%v", strings.Join(errs, "\n"))
	}
}

func getAllNetworks() ([]types.NetworkResource, error) {
	var networks []types.NetworkResource
	_, b, err := request.SockRequest("GET", "/networks", nil, request.DaemonHost())
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(b, &networks); err != nil {
		return nil, err
	}
	return networks, nil
}

func deleteAllPlugins(t testingT, dockerBinary string) {
	plugins, err := getAllPlugins()
	if err != nil {
		t.Fatalf("%v", err)
	}
	var errs []string
	for _, p := range plugins {
		pluginName := p.Name
		status, b, err := request.SockRequest("DELETE", "/plugins/"+pluginName+"?force=1", nil, request.DaemonHost())
		if err != nil {
			errs = append(errs, err.Error())
			continue
		}
		if status != http.StatusOK {
			errs = append(errs, fmt.Sprintf("error deleting plugin %s: %s", p.Name, string(b)))
		}
	}
	if len(errs) > 0 {
		t.Fatalf("%v", strings.Join(errs, "\n"))
	}
}

func getAllPlugins() (types.PluginsListResponse, error) {
	var plugins types.PluginsListResponse
	_, b, err := request.SockRequest("GET", "/plugins", nil, request.DaemonHost())
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(b, &plugins); err != nil {
		return nil, err
	}
	return plugins, nil
}
