package infra

import (
	"encoding/json"
	"fmt"
	"os/exec"
)

// DockerListContainers lista contenedores Docker. Si all es true, incluye los detenidos.
func DockerListContainers(all bool) ([]ContainerInfo, error) {
	args := []string{"ps", "--format", "{{json .}}", "--no-trunc"}
	if all {
		args = append(args, "-a")
	}

	out, err := exec.Command("docker", args...).Output()
	if err != nil {
		return nil, fmt.Errorf("docker ps: %w", err)
	}

	if len(out) == 0 {
		return nil, nil
	}

	var containers []ContainerInfo
	for _, line := range splitLines(out) {
		if len(line) == 0 {
			continue
		}
		var raw struct {
			ID      string `json:"ID"`
			Names   string `json:"Names"`
			Image   string `json:"Image"`
			Status  string `json:"Status"`
			State   string `json:"State"`
			Ports   string `json:"Ports"`
			Created string `json:"CreatedAt"`
			Labels  string `json:"Labels"`
		}
		if err := json.Unmarshal(line, &raw); err != nil {
			continue
		}
		containers = append(containers, ContainerInfo{
			ID:      raw.ID[:12],
			Name:    raw.Names,
			Image:   raw.Image,
			Status:  raw.Status,
			State:   raw.State,
			Ports:   raw.Ports,
			Created: raw.Created,
			Labels:  parseLabels(raw.Labels),
		})
	}

	return containers, nil
}

// splitLines divide bytes en líneas individuales.
func splitLines(data []byte) [][]byte {
	var lines [][]byte
	start := 0
	for i, b := range data {
		if b == '\n' {
			lines = append(lines, data[start:i])
			start = i + 1
		}
	}
	if start < len(data) {
		lines = append(lines, data[start:])
	}
	return lines
}

// parseLabels convierte "key=val,key2=val2" en map.
func parseLabels(s string) map[string]string {
	m := make(map[string]string)
	if s == "" {
		return m
	}
	for _, part := range splitByComma(s) {
		for i := 0; i < len(part); i++ {
			if part[i] == '=' {
				m[part[:i]] = part[i+1:]
				break
			}
		}
	}
	return m
}

func splitByComma(s string) []string {
	var parts []string
	start := 0
	for i := 0; i < len(s); i++ {
		if s[i] == ',' {
			parts = append(parts, s[start:i])
			start = i + 1
		}
	}
	if start < len(s) {
		parts = append(parts, s[start:])
	}
	return parts
}
