package mail

import (
	"fmt"
	"strings"

	"github.com/google/uuid"
)

var systemFolderSlugs = map[string]string{
	"inbox":   "inbox",
	"sent":    "sent",
	"drafts":  "drafts",
	"trash":   "trash",
	"archive": "archive",
	"spam":    "spam",
}

// HiddenMailboxExclusion decides whether spam/trash should be filtered out of list/search
// results. Explicit folder or label targeting spam/trash disables the matching exclusion.
func HiddenMailboxExclusion(folder, label string, includeSpam, includeTrash bool) (excludeSpam, excludeTrash bool) {
	folder = strings.ToLower(strings.TrimSpace(folder))
	label = strings.ToLower(strings.TrimSpace(label))
	excludeSpam = !includeSpam && folder != "spam" && label != "spam"
	excludeTrash = !includeTrash && folder != "trash" && label != "trash"
	return excludeSpam, excludeTrash
}

func AppendHiddenMailboxExclusion(base string, args []any, argIdx int, excludeSpam, excludeTrash bool) (string, []any, int) {
	if !excludeSpam && !excludeTrash {
		return base, args, argIdx
	}

	folderTypes := make([]string, 0, 2)
	if excludeSpam {
		folderTypes = append(folderTypes, "spam")
	}
	if excludeTrash {
		folderTypes = append(folderTypes, "trash")
	}
	base += fmt.Sprintf(`
		  AND NOT EXISTS (
		    SELECT 1 FROM mail_folders f
		    WHERE f.id = m.folder_id AND f.account_id = m.account_id
		      AND f.folder_type = ANY($%d)
		  )`, argIdx)
	args = append(args, folderTypes)
	argIdx++

	if excludeSpam {
		base += fmt.Sprintf(" AND NOT ($%d = ANY(m.labels))", argIdx)
		args = append(args, "spam")
		argIdx++
	}
	if excludeTrash {
		base += fmt.Sprintf(" AND NOT ($%d = ANY(m.labels))", argIdx)
		args = append(args, "trash")
		argIdx++
	}
	return base, args, argIdx
}

// folderFilterClause builds a SQL fragment that resolves a folder query param to
// mail_folders rows. System slugs (e.g. "inbox") match folder_type; UUIDs match
// folder id; everything else matches display name case-insensitively.
func folderFilterClause(folder string, argIdx int) (clause string, arg any, ok bool) {
	folder = strings.TrimSpace(folder)
	if folder == "" {
		return "", nil, false
	}
	if _, err := uuid.Parse(folder); err == nil {
		return fmt.Sprintf(" AND m.folder_id = $%d", argIdx), folder, true
	}
	if folderType, known := systemFolderSlugs[strings.ToLower(folder)]; known {
		return fmt.Sprintf(
			" AND m.folder_id IN (SELECT id FROM mail_folders WHERE folder_type = $%d AND account_id = m.account_id)",
			argIdx,
		), folderType, true
	}
	return fmt.Sprintf(
		" AND m.folder_id IN (SELECT id FROM mail_folders WHERE LOWER(name) = LOWER($%d) AND account_id = m.account_id)",
		argIdx,
	), folder, true
}
