package httpserver

import (
	"encoding/json"
	"io"
	"os"
	"path/filepath"
)

func (fs *FileServer) findSpecialFile(folder string) (configFile, error) {
	var config configFile

	// disable G304 (CWE-22): Potential file inclusion via variable
	// #nosec G304
	file, err := os.Open(folder)
	if err != nil {
		return config, err
	}

	fis, err := file.Readdir(-1)
	if err != nil {
		return config, err
	}

	for _, fi := range fis {
		if fi.Name() == ".goshs" {
			openFile := filepath.Join(file.Name(), fi.Name())

			// disable G304 (CWE-22): Potential file inclusion via variable
			// #nosec G304
			configFileDisk, err := os.Open(openFile)
			if err != nil {
				return config, err
			}

			configFileBytes, err := io.ReadAll(configFileDisk)
			if err != nil {
				return config, err
			}

			if err := json.Unmarshal(configFileBytes, &config); err != nil {
				return config, err
			}

			return config, nil
		}
	}

	return config, nil
}

// findEffectiveACL walks up the directory tree from dir toward the webroot,
// returning the nearest configFile found. This allows a .goshs placed in a
// parent directory to apply recursively to all subdirectories without
// leaking upward past the webroot.
func (fs *FileServer) findEffectiveACL(dir string) (configFile, error) {
	webroot := filepath.Clean(fs.Webroot)
	current := filepath.Clean(dir)

	for {
		config, err := fs.findSpecialFile(current)
		if err != nil {
			return configFile{}, err
		}
		if config.Auth != "" || len(config.Block) > 0 {
			return config, nil
		}
		// Stop once we have checked the webroot itself
		if current == webroot {
			break
		}
		parent := filepath.Dir(current)
		if parent == current {
			// Reached filesystem root – guard against infinite loop
			break
		}
		current = parent
	}

	return configFile{}, nil
}
