package io

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

	"github.com/acepanel/panel/pkg/chattr"
)

// Write 写入文件
func Write(path string, data string, permission os.FileMode) error {
	if err := os.MkdirAll(filepath.Dir(path), permission); err != nil {
		return err
	}

	iFlag, aFlag := false, false
	file, err := os.OpenFile(path, os.O_RDONLY, permission)
	if err == nil {
		iFlag, _ = chattr.IsAttr(file, chattr.FS_IMMUTABLE_FL)
		aFlag, _ = chattr.IsAttr(file, chattr.FS_APPEND_FL)
		if iFlag {
			_ = chattr.UnsetAttr(file, chattr.FS_IMMUTABLE_FL)
		}
		if aFlag {
			_ = chattr.UnsetAttr(file, chattr.FS_APPEND_FL)
		}

		// 关闭文件重新以写入方式打开
		if err = file.Close(); err != nil {
			return err
		}
	}
	file, err = os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, permission)
	if err != nil {
		return err
	}
	defer func(file *os.File) {
		_ = file.Close()
	}(file)

	_, err = file.WriteString(data)
	if err != nil {
		return err
	}

	if iFlag {
		_ = chattr.SetAttr(file, chattr.FS_IMMUTABLE_FL)
	}
	if aFlag {
		_ = chattr.SetAttr(file, chattr.FS_APPEND_FL)
	}

	return nil
}

// WriteAppend 追加写入文件
func WriteAppend(path string, data string, permission os.FileMode) error {
	iFlag := false
	file, err := os.OpenFile(path, os.O_RDONLY, permission)
	if err == nil {
		iFlag, _ = chattr.IsAttr(file, chattr.FS_IMMUTABLE_FL)
		if iFlag {
			_ = chattr.UnsetAttr(file, chattr.FS_IMMUTABLE_FL)
		}

		// 关闭文件重新以写入方式打开
		if err = file.Close(); err != nil {
			return err
		}
	}
	file, err = os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, permission)
	if err != nil {
		return err
	}
	defer func(file *os.File) {
		_ = file.Close()
	}(file)

	_, err = file.WriteString(data)
	if err != nil {
		return err
	}

	if iFlag {
		_ = chattr.SetAttr(file, chattr.FS_IMMUTABLE_FL)
	}

	return nil
}

// Read 读取文件
func Read(path string) (string, error) {
	data, err := os.ReadFile(path)
	return string(data), err
}

// IsSymlink 判读是否为软链接
func IsSymlink(mode os.FileMode) bool {
	return mode&os.ModeSymlink != 0
}

// IsHidden 判断是否为隐藏文件
func IsHidden(path string) bool {
	_, file := filepath.Split(path)
	return strings.HasPrefix(file, ".")
}

// GetSymlink 获取软链接目标
func GetSymlink(path string) string {
	linkPath, err := os.Readlink(path)
	if err != nil {
		return ""
	}
	return linkPath
}
