package docker

import (
	"runtime"
	"strings"
)

// DiagCategory classifies a Docker connectivity error.
type DiagCategory string

const (
	DiagSocketNotFound    DiagCategory = "socket_not_found"
	DiagConnectionRefused DiagCategory = "connection_refused"
	DiagPermissionDenied  DiagCategory = "permission_denied"
	DiagTimeout           DiagCategory = "timeout"
	DiagTLSError          DiagCategory = "tls_error"
	DiagUnknown           DiagCategory = "unknown"
)

// Diagnostic holds a classified error with platform-specific hints.
type Diagnostic struct {
	Category DiagCategory `json:"category"`
	Hints    []string     `json:"hints"`
	Platform string       `json:"platform"`
}

// Diagnose classifies a Docker Ping error and returns platform-aware hints.
// Pure function — takes an error and platform, returns structured diagnostics.
func Diagnose(err error, platform string) Diagnostic {
	if platform == "" {
		platform = runtime.GOOS
	}

	msg := ""
	if err != nil {
		msg = strings.ToLower(err.Error())
	}

	cat := classifyError(msg)

	return Diagnostic{
		Category: cat,
		Hints:    hintsFor(cat, platform),
		Platform: platform,
	}
}

func classifyError(msg string) DiagCategory {
	switch {
	case containsAny(msg, "no such file or directory", "cannot find the file specified", "the system cannot find"):
		return DiagSocketNotFound
	case containsAny(msg, "connection refused"):
		return DiagConnectionRefused
	case containsAny(msg, "permission denied", "access is denied"):
		return DiagPermissionDenied
	case containsAny(msg, "context deadline exceeded", "i/o timeout", "timeout"):
		return DiagTimeout
	case containsAny(msg, "tls:", "certificate"):
		return DiagTLSError
	default:
		return DiagUnknown
	}
}

func containsAny(s string, substrs ...string) bool {
	for _, sub := range substrs {
		if strings.Contains(s, sub) {
			return true
		}
	}
	return false
}

var hintTable = map[DiagCategory]map[string][]string{
	DiagSocketNotFound: {
		"windows": {
			"Docker Desktop does not appear to be running.",
			"Start Docker Desktop from the Start Menu or system tray.",
			"If using a custom socket path, check the DOCKER_HOST environment variable.",
		},
		"linux": {
			"Docker daemon is not running.",
			"Start it with: sudo systemctl start docker",
			"If using a custom socket path, check the DOCKER_HOST environment variable.",
		},
		"darwin": {
			"Docker Desktop does not appear to be running.",
			"Start it from Applications or run: open -a Docker",
			"If using a custom socket path, check the DOCKER_HOST environment variable.",
		},
	},
	DiagConnectionRefused: {
		"windows": {
			"Docker Desktop is starting up — wait ~30 seconds and retry.",
			"If it persists, restart Docker Desktop.",
		},
		"linux": {
			"Docker daemon is starting up.",
			"Check status with: sudo systemctl status docker",
		},
		"darwin": {
			"Docker Desktop is starting up.",
			"Check the whale icon in the menu bar for status.",
		},
	},
	DiagPermissionDenied: {
		"windows": {
			"Run the application as Administrator, or add your user to the docker-users group.",
		},
		"linux": {
			"Add your user to the docker group: sudo usermod -aG docker $USER",
			"Then log out and log back in for the change to take effect.",
		},
		"darwin": {
			"Check Docker Desktop settings under Resources > File Sharing.",
		},
	},
	DiagTimeout: {
		"windows": {
			"Docker Desktop may be overloaded or hanging.",
			"Try restarting Docker Desktop.",
		},
		"linux": {
			"Docker daemon may be overloaded.",
			"Check logs with: journalctl -u docker --no-pager -n 50",
		},
		"darwin": {
			"Docker Desktop may be unresponsive.",
			"Restart it from the menu bar whale icon.",
		},
	},
	DiagTLSError: {
		"windows": {
			"Check Docker TLS certificate configuration.",
			"Verify the DOCKER_TLS_VERIFY environment variable.",
		},
		"linux": {
			"Verify certificates in ~/.docker/ match the daemon configuration.",
		},
		"darwin": {
			"Check ~/.docker/ TLS configuration.",
		},
	},
	DiagUnknown: {
		"windows": {
			"An unexpected Docker error occurred.",
			"Try restarting Docker Desktop.",
		},
		"linux": {
			"An unexpected Docker error occurred.",
			"Check daemon status with: sudo systemctl status docker",
		},
		"darwin": {
			"An unexpected Docker error occurred.",
			"Try restarting Docker Desktop.",
		},
	},
}

func hintsFor(cat DiagCategory, platform string) []string {
	catHints, ok := hintTable[cat]
	if !ok {
		catHints = hintTable[DiagUnknown]
	}
	hints, ok := catHints[platform]
	if !ok {
		hints = catHints["linux"] // fallback
	}
	return hints
}
