/*
 * Copyright 2026 Oleg Borodin <onborodin@gmail.com>
 */
package fileoper

import (
	"context"
	"net/http"
	"regexp"
	"slices"
	"strings"

	"mstore/pkg/filecli"
)

// ListCollections
type ListCollectionsParams struct {
	Path     string
	PathType string `param:"pathType"`
}
type ListCollectionsResult struct {
	Collections []string `json:"collection,omitempty"`
}

func (oper *Operator) ListCollections(ctx context.Context, operatorID string, param *ListCollectionsParams) (int, *ListCollectionsResult, error) {
	var err error
	res := &ListCollectionsResult{
		Collections: make([]string, 0),
	}

	collectionList := make([]string, 0)
	switch param.PathType {
	case filecli.PathTypeRegexp:
		collectionList, err = oper.listCollectionsWithRegexp(ctx, param.Path)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
	case filecli.PathTypePrefix:
		param.Path, err = cleanFilepath(param.Path)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}

		collectionList, err = oper.listCollectionsWithPrefix(ctx, param.Path)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}
	default:
		param.Path, err = cleanFilepath(param.Path)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}

		collectionList, err = oper.listAllCollections(ctx)
		if err != nil {
			code := http.StatusInternalServerError
			return code, res, err
		}

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

func (oper *Operator) listCollectionsWithPrefix(ctx context.Context, prefix string) ([]string, error) {
	var err error
	res := make([]string, 0)

	fileDescrs, err := oper.mdb.ListAllFiles(ctx) // TODO
	if err != nil {
		return res, err
	}
	collMap := make(map[string]bool)
	for _, item := range fileDescrs {
		_, exists := collMap[item.Collection]
		if !exists {
			collMap[item.Collection] = true
		}
	}
	res = make([]string, 0)
	for key, _ := range collMap {
		if strings.HasPrefix(key, prefix) {
			res = append(res, key)
		}
	}
	slices.Sort(res)
	return res, err
}

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

	re, err := regexp.Compile(regex)
	if err != nil {
		return res, err
	}

	fileDescrs, err := oper.mdb.ListAllFiles(ctx) // TODO
	if err != nil {
		return res, err
	}
	collMap := make(map[string]bool)
	for _, item := range fileDescrs {
		_, exists := collMap[item.Collection]
		if !exists {
			collMap[item.Collection] = true
		}
	}
	res = make([]string, 0)
	for key, _ := range collMap {
		if re.MatchString(key) {
			res = append(res, key)
		}
	}
	slices.Sort(res)
	return res, err
}

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

	fileDescrs, err := oper.mdb.ListAllFiles(ctx) // TODO
	if err != nil {
		return res, err
	}
	collMap := make(map[string]bool)
	for _, item := range fileDescrs {
		_, exists := collMap[item.Collection]
		if !exists {
			collMap[item.Collection] = true
		}
	}
	res = make([]string, 0)
	for key, _ := range collMap {
		res = append(res, key)
	}
	slices.Sort(res)
	return res, err
}
