package handler

import (
	"errors"
	"io/fs"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"git.pyer.club/kingecg/gologger"
)

type FileHandler struct {
	Root    string
	Default string
	http.FileSystem
}

func (f FileHandler) Open(name string) (http.File, error) {
	l := gologger.GetLogger("filehandler")

	if strings.HasPrefix(name, "../") {
		return nil, errors.New("not permitted")
	}

	rPath := filepath.Join(f.Root, strings.TrimPrefix(name, "/"))
	l.Debug("access:", rPath)
	// if rPath == f.Root {
	// 	if f.Default == "" {
	// 		return nil, errors.New("not permit list dir")
	// 	}
	// 	rPath = filepath.Join(rPath, f.Default)
	// }

	fInfo, _, err := FileExists(rPath)
	if err != nil {
		l.Error("access file error:", rPath, err)
		return nil, err
	}

	if fInfo.IsDir() && rPath != strings.TrimSuffix(f.Root, "/") {
		return nil, errors.New("not permit list dir")
	}

	if fInfo.Mode() == fs.ModeSymlink {
		return nil, errors.New("not permit follow symbol link")
	}

	fp, err := os.Open(rPath)
	if err != nil {
		l.Error("open file fail", err)
		return nil, err
	}
	return fp, nil
}

func FileExists(name string) (os.FileInfo, bool, error) {
	info, err := os.Stat(name)
	if err != nil {
		return nil, os.IsExist(err), err
	}
	return info, true, nil
}

func NewFileHandler(f FileHandler) http.Handler {
	return http.FileServer(f)
}
