package platform

import (
	"errors"
	"os"
	"path/filepath"
	"strings"
)

func ValidateRestoreTarget(target, restoreRoot string, inPlace, confirmed bool) (string, error) {
	if !filepath.IsAbs(target) {
		return "", errors.New("validation: restore target must be absolute")
	}
	clean := filepath.Clean(target)
	if clean == "/" || clean == "/boot" || clean == "/etc" || clean == "/usr" || clean == "/var" {
		return "", errors.New("validation: protected system restore target")
	}
	if !inPlace {
		root := filepath.Clean(restoreRoot)
		if clean != root && !strings.HasPrefix(clean, root+string(os.PathSeparator)) {
			return "", errors.New("validation: staging restore must remain below restoreRoot")
		}
		if err := rejectSymlinks(root, clean); err != nil {
			return "", err
		}
	} else if !confirmed {
		return "", errors.New("validation: in-place restore requires explicit confirmation")
	}
	if inPlace {
		anchor := string(os.PathSeparator) + strings.Split(strings.TrimPrefix(clean, string(os.PathSeparator)), string(os.PathSeparator))[0]
		if err := rejectSymlinks(anchor, clean); err != nil {
			return "", err
		}
	}
	return clean, nil
}

func rejectSymlinks(root, target string) error {
	relative, err := filepath.Rel(root, target)
	if err != nil {
		return err
	}
	current := root
	for _, component := range strings.Split(relative, string(os.PathSeparator)) {
		if component == "." || component == "" {
			continue
		}
		current = filepath.Join(current, component)
		info, err := os.Lstat(current)
		if errors.Is(err, os.ErrNotExist) {
			return nil
		}
		if err != nil {
			return err
		}
		if info.Mode()&os.ModeSymlink != 0 {
			return errors.New("validation: restore target traverses a symlink")
		}
	}
	return nil
}
