//go:build linux
// +build linux

package file

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/dustin/go-humanize"
)

type FileInfo struct {
	FileType     string `json:"fileType"`     // 文件类型
	FileMode     string `json:"fileMode"`     // 文件的权限
	LinkCount    int64  `json:"linkCount"`    // 硬链接数目
	Owner        string `json:"owner"`        // 所属用户
	Group        string `json:"group"`        // 所属组
	Size         string `json:"size"`         // 文件的大小
	ModifiedTime int64  `json:"modifiedTime"` // 最后修改时间，单位为秒
	FileName     string `json:"fileName"`     // 文件的名称
}

func GetFileInfo(dir, suffix string) ([]FileInfo, error) {
	var files []FileInfo

	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if path == dir {
			return nil // 跳过当前目录
		}

		fileType := "file"
		if info.IsDir() {
			fileType = "directory"
		} else if info.Mode()&os.ModeSymlink != 0 {
			fileType = "symlink"
		}

		// check if match suffix
		if (suffix != "" && filepath.Ext(path) == suffix) || suffix == "" {
			stat, ok := info.Sys().(*syscall.Stat_t)
			if !ok {
				return fmt.Errorf("not a syscall.Stat_t")
			}
			userInfo, err := user.LookupId(fmt.Sprint(stat.Uid))
			if err != nil {
				return err
			}
			groupInfo, err := user.LookupGroupId(fmt.Sprint(stat.Gid))
			if err != nil {
				return err
			}
			humanReadableSize := humanize.Bytes(uint64(info.Size()))
			fileInfo := FileInfo{
				FileType:     fileType,
				FileMode:     info.Mode().String(),
				LinkCount:    int64(info.Sys().(*syscall.Stat_t).Nlink),
				Owner:        userInfo.Username,
				Group:        groupInfo.Name,
				Size:         strings.ToUpper(humanReadableSize),
				ModifiedTime: info.ModTime().Unix(),
				FileName:     info.Name(),
			}
			files = append(files, fileInfo)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return files, nil
}
