package cmds

import (
	"agent/client/events"
	"agent/commons/adata"
	"agent/commons/debug"
	"agent/commons/utils"
	"agent/defines/derrs"
	"agent/defines/devent/dtype"
	"bytes"
	"encoding/csv"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
)

func normalizePath(path string) string {
	if path == "/" || path == "\\" {
		return "/"
	}
	path = strings.TrimSpace(path)
	if strings.HasSuffix(path, ":") {
		path += string(os.PathSeparator)
	}
	path, err := filepath.Abs(path)
	if err != nil {
		path = filepath.Clean(path)
	}
	return filepath.ToSlash(path)
}

func list2(paths []string, deep int, full bool, expandPath bool) (res [][]string, err error) {
	for _, path_ := range paths {
		path_ = filepath.ToSlash(path_)
		if expandPath {
			parts := strings.Split(path_, "/")
			// В линуксе, после разделения по слешу, получим ["", ""]
			if path_ == "/" {
				// Поэтому возвращаем слеш
				parts = []string{"/"}
			} else {
				// В линуксе, после разделения по слешу, корневой элемент будет пустым ""
				if strings.HasPrefix(path_, "/") {
					// Поэтому возвращаем слеш
					parts[0] = "/"
				}
			}
			if len(parts) > 1 {
				path_ := strings.Join(parts[:len(parts)-1], string(os.PathSeparator))
				if err = utils.DirPathWalk(path_, func(entry fs.DirEntry, path string, count int, depth int) error {
					item := createItem(entry, path, count, full)
					res = append(res, item)
					return nil
				}); err != nil {
					debug.Log(err)
				}
			}
		}
		if err = utils.DirTraverse(path_, deep, func(entry fs.DirEntry, path string, count int, depth int) error {
			item := createItem(entry, path, count, full)
			res = append(res, item)
			return nil
		}); err != nil {
			debug.Log(err)
		}
	}

	return res, nil
}

func listFoldersToResultEvent(eventIn IEvent, path ...string) (eventOut IEvent, err error) {
	deep := 0
	full := true
	expandPath := false

	data, err := listFoldersToData(deep, full, expandPath, path...)
	if err != nil {
		return nil, err
	}

	return events.NewResultEvent(eventIn, dtype.Result, events.NewResultEventOpts{
		Data: adata.NewDataFromMem(data),
	}), nil
}

func listFoldersToData(deep int, full bool, expandPath bool, paths ...string) (data []byte, err error) {
	var records [][]string
	for _, p := range paths {
		res, err := listFolder(p, deep, full, expandPath)
		if err != nil {
			return nil, err
		}
		records = append(records, res...)
	}

	dataBuffer := bytes.Buffer{}
	csvWriter := csv.NewWriter(&dataBuffer)
	if err = csvWriter.WriteAll(records); err != nil {
		return nil, err
	}

	csvWriter.Flush()
	if err = csvWriter.Error(); err != nil {
		return nil, err
	}

	return dataBuffer.Bytes(), nil
}

func checkFolderAccess(path string) error {
	info, err := os.Stat(path)
	if err != nil {
		return err
	}
	if !info.IsDir() {
		return derrs.NewIncorrectParamsError("path is not a directory")
	}
	_, err = os.ReadDir(path)
	return err
}
