package store

import (
	"fmt"

	"github.com/prometheus/alertmanager/pkg/labels"

	"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
)

// buildLabelMatcherCondition builds SQL for a label matcher with Prometheus semantics.
// For MySQL/PostgreSQL, it uses JSON functions, and
// for SQLite, it uses GLOB patterns to find matching labels.
func buildLabelMatcherCondition(dialect migrator.Dialect, column string, m *labels.Matcher) (string, []any, error) {
	if dialect.DriverName() == migrator.SQLite {
		return buildLabelMatcherGlob(column, m)
	}
	return buildLabelMatcherJSON(dialect, column, m)
}

func buildLabelKeyExistsCondition(dialect migrator.Dialect, column string, key string) (string, []any, error) {
	if dialect.DriverName() == migrator.SQLite {
		return globKeyExists(column, key)
	}
	return jsonKeyExists(dialect, column, key)
}

func buildLabelKeyMissingCondition(dialect migrator.Dialect, column string, key string) (string, []any, error) {
	if dialect.DriverName() == migrator.SQLite {
		return globKeyMissing(column, key)
	}
	return jsonKeyMissing(dialect, column, key)
}

func buildLabelMatcherGlob(column string, m *labels.Matcher) (string, []any, error) {
	switch {
	case m.Type == labels.MatchEqual && m.Value == "":
		eqSQL, eqArgs, _ := globEquals(column, m.Name, "")
		missingSQL, missingArgs, _ := globKeyMissing(column, m.Name)
		return "(" + eqSQL + " OR " + missingSQL + ")", append(eqArgs, missingArgs...), nil
	case m.Type == labels.MatchEqual:
		return globEquals(column, m.Name, m.Value)
	case m.Type == labels.MatchNotEqual:
		return globNotEquals(column, m.Name, m.Value)
	default:
		return "", nil, fmt.Errorf("unsupported matcher type: %v", m.Type)
	}
}

func buildLabelMatcherJSON(dialect migrator.Dialect, column string, m *labels.Matcher) (string, []any, error) {
	switch {
	case m.Type == labels.MatchEqual && m.Value == "":
		eqSQL, eqArgs := jsonEquals(dialect, column, m.Name, "")
		missingSQL, missingArgs, err := jsonKeyMissing(dialect, column, m.Name)
		if err != nil {
			return "", nil, err
		}
		return "(" + eqSQL + " OR " + missingSQL + ")", append(eqArgs, missingArgs...), nil
	case m.Type == labels.MatchEqual:
		sql, args := jsonEquals(dialect, column, m.Name, m.Value)
		return sql, args, nil
	case m.Type == labels.MatchNotEqual:
		sql, args := jsonNotEquals(dialect, column, m.Name, m.Value)
		return sql, args, nil
	default:
		return "", nil, fmt.Errorf("unsupported matcher type: %v", m.Type)
	}
}
