package persistence

import (
	"strings"

	. "github.com/Masterminds/squirrel"
	"github.com/deluan/navidrome/log"
	"github.com/kennygrant/sanitize"
)

const searchTable = "search"

func (r sqlRepository) index(id string, text ...string) error {
	sanitizedText := strings.Builder{}
	for _, txt := range text {
		sanitizedText.WriteString(strings.TrimSpace(sanitize.Accents(strings.ToLower(txt))) + " ")
	}

	values := map[string]interface{}{
		"id":        id,
		"item_type": r.tableName,
		"full_text": strings.TrimSpace(sanitizedText.String()),
	}
	update := Update(searchTable).Where(Eq{"id": id}).SetMap(values)
	count, err := r.executeSQL(update)
	if err != nil {
		return err
	}
	if count > 0 {
		return nil
	}
	insert := Insert(searchTable).SetMap(values)
	_, err = r.executeSQL(insert)
	return err
}

func (r sqlRepository) doSearch(q string, offset, size int, results interface{}, orderBys ...string) error {
	q = strings.TrimSpace(sanitize.Accents(strings.ToLower(strings.TrimSuffix(q, "*"))))
	if len(q) < 2 {
		return nil
	}
	sq := r.newSelectWithAnnotation(r.tableName + ".id").Columns("*")
	sq = sq.Limit(uint64(size)).Offset(uint64(offset))
	if len(orderBys) > 0 {
		sq = sq.OrderBy(orderBys...)
	}
	sq = sq.Join("search").Where("search.id = " + r.tableName + ".id")
	parts := strings.Split(q, " ")
	for _, part := range parts {
		sq = sq.Where(Or{
			Like{"full_text": part + "%"},
			Like{"full_text": "%" + part + "%"},
		})
	}
	err := r.queryAll(sq, results)
	return err
}

func (r sqlRepository) cleanSearchIndex() error {
	del := Delete(searchTable).Where(Eq{"item_type": r.tableName}).Where("id not in (select id from " + r.tableName + ")")
	c, err := r.executeSQL(del)
	if err != nil {
		return err
	}
	if c > 0 {
		log.Debug(r.ctx, "Clean-up search index", "table", r.tableName, "totalDeleted", c)
	}
	return nil
}
