/*
 * Copyright 2026 Oleg Borodin <onborodin@gmail.com>
 *
 * This work is published and licensed under a Creative Commons
 * Attribution-NonCommercial-NoDerivatives 4.0 International License.
 *
 * Distribution of this work is permitted, but commercial use and
 * modifications are strictly prohibited.
 */
package fileoper

import (
	"context"
	"net/http"
	"path/filepath"
	"regexp"
	"strings"

	"mstore/pkg/descr"
	"mstore/pkg/filecli"
)

// ListFiles
type ListFilesParams struct {
	Filepath string
	PathType string `param:"pathType"`
}
type ListFilesResult struct {
	Files []descr.File `json:"files,omitempty"`
}

func (oper *Operator) ListFiles(ctx context.Context, operatorID string, params *ListFilesParams) (int, *ListFilesResult, error) {
	var err error
	res := &ListFilesResult{}
	switch params.PathType {
	case filecli.PathTypeRegexp:
		files, err := oper.listFilesWithRegex(ctx, params.Filepath)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
		res.Files = files
	case filecli.PathTypePrefix:
		params.Filepath, err = cleanFilepath(params.Filepath)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
		params.Filepath, err = cleanFilepath(params.Filepath)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}

		files, err := oper.listFilesWithPrefix(ctx, params.Filepath)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
		res.Files = files
	default:
		params.Filepath, err = cleanFilepath(params.Filepath)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
		params.Filepath, err = cleanFilepath(params.Filepath)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
		files, err := oper.listFilesInCollection(ctx, params.Filepath)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
		res.Files = files

	}
	code := http.StatusOK
	return code, res, err
}

func (oper *Operator) listFilesInCollection(ctx context.Context, collection string) ([]descr.File, error) {
	var err error
	res := make([]descr.File, 0)
	files, err := oper.mdb.ListFilesByCollection(ctx, collection)
	if err != nil {
		return res, err
	}
	res = files
	return res, err
}

func (oper *Operator) listFilesWithPrefix(ctx context.Context, prefix string) ([]descr.File, error) {
	var err error
	res := make([]descr.File, 0)
	files, err := oper.mdb.ListAllFiles(ctx)
	if err != nil {
		return res, err
	}
	for _, file := range files {
		fullpath := filepath.Join(file.Collection, file.Name)
		if strings.HasPrefix(fullpath, prefix) {
			res = append(res, file)
		}
	}
	return res, err
}

func (oper *Operator) listFilesWithRegex(ctx context.Context, regex string) ([]descr.File, error) {
	var err error
	res := make([]descr.File, 0)

	re, err := regexp.Compile(regex)
	if err != nil {
		return res, err
	}
	files, err := oper.mdb.ListAllFiles(ctx)
	if err != nil {
		return res, err
	}
	for _, file := range files {
		fullpath := filepath.Join(file.Collection, file.Name)
		if re.MatchString(fullpath) {
			res = append(res, file)
		}
	}
	return res, err
}
