package mysql

import (
	"reflect"
	"testing"

	"github.com/tidbcloud/pov-service/internal/common/options"
)

func Test_column2Query(t *testing.T) {
	type args struct {
		opt options.ColumnOption
	}
	tests := []struct {
		name      string
		args      args
		wantWhere []string
		wantArgs  []any
	}{
		{
			name: "Test_Value",
			args: args{
				opt: options.ColumnOption{Column: "col1", Value: "val1"},
			},
			wantWhere: []string{"col1 = ?"},
			wantArgs:  []any{"val1"},
		},
		{
			name: "Test_ValueNot",
			args: args{
				opt: options.ColumnOption{Column: "col1", ValueNot: "val1"},
			},
			wantWhere: []string{"col1 != ?"},
			wantArgs:  []any{"val1"},
		},
		{
			name: "Test_Values",
			args: args{
				opt: options.ColumnOption{Column: "col1", Values: []any{"val1", "val2"}},
			},
			wantWhere: []string{"col1 IN (?,?)"},
			wantArgs:  []any{"val1", "val2"},
		},
		{
			name: "Test_ValuesNot",
			args: args{
				opt: options.ColumnOption{Column: "col1", ValuesNot: []any{"val1", "val2"}},
			},
			wantWhere: []string{"col1 NOT IN (?,?)"},
			wantArgs:  []any{"val1", "val2"},
		},
		{
			name: "Test_Large",
			args: args{
				opt: options.ColumnOption{Column: "col1", Large: 10},
			},
			wantWhere: []string{"col1 > ?"},
			wantArgs:  []any{10},
		},
		{
			name: "Test_LargeOrEqual",
			args: args{
				opt: options.ColumnOption{Column: "col1", LargeOrEqual: 10},
			},
			wantWhere: []string{"col1 >= ?"},
			wantArgs:  []any{10},
		},
		{
			name: "Test_Less",
			args: args{
				opt: options.ColumnOption{Column: "col1", Less: 10},
			},
			wantWhere: []string{"col1 < ?"},
			wantArgs:  []any{10},
		},
		{
			name: "Test_LessOrEqual",
			args: args{
				opt: options.ColumnOption{Column: "col1", LessOrEqual: 10},
			},
			wantWhere: []string{"col1 <= ?"},
			wantArgs:  []any{10},
		},
		{
			name: "Test_Like",
			args: args{
				opt: options.ColumnOption{Column: "col1", Like: "%test%"},
			},
			wantWhere: []string{"col1 LIKE ?"},
			wantArgs:  []any{"%test%"},
		},
		{
			name: "Test_MultipleOptions",
			args: args{
				opt: options.ColumnOption{Column: "col1", Value: "val1", Large: 10},
			},
			wantWhere: []string{"col1 = ?", "col1 > ?"},
			wantArgs:  []any{"val1", 10},
		},
		{
			name: "Test_NoOptions",
			args: args{
				opt: options.ColumnOption{Column: "col1"},
			},
			wantWhere: []string{},
			wantArgs:  []any{},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			gotWhereConditions, gotArgs := column2Query(tt.args.opt)
			if !reflect.DeepEqual(gotWhereConditions, tt.wantWhere) {
				t.Errorf("column2Query() gotWhereConditions = %v, %v", gotWhereConditions, tt.wantWhere)
			}
			if !reflect.DeepEqual(gotArgs, tt.wantArgs) {
				t.Errorf("column2Query() gotArgs = %v, %v", gotArgs, tt.wantArgs)
			}
		})
	}
}

func Test_buildQueries(t *testing.T) {
	type args struct {
		options options.TableOption
	}
	tests := []struct {
		name      string
		args      args
		wantQuery string
		wantArgs  []any
	}{
		{
			name: "Test_SingleFilter",
			args: args{
				options: options.TableOption{
					Filters: []options.ColumnOption{{
						Column: "col1", Value: "val1"},
					},
				},
			},
			wantQuery: "WHERE col1 = ?",
			wantArgs:  []any{"val1"},
		},
		{
			name: "Test_MultipleFilters",
			args: args{
				options: options.TableOption{
					Filters: []options.ColumnOption{
						{Column: "col1", Value: "val1"},
						{Column: "col2", Large: 10},
					},
				},
			},
			wantQuery: "WHERE col1 = ? AND col2 > ?",
			wantArgs:  []any{"val1", 10},
		},
		{
			name: "Test_OrderBy",
			args: args{
				options: options.TableOption{
					OrderBy: "col1 DESC",
				},
			},
			wantQuery: " ORDER BY col1 DESC",
			wantArgs:  []any{},
		},
		{
			name: "Test_Limit",
			args: args{
				options: options.TableOption{
					Limit: 10,
				},
			},
			wantQuery: " LIMIT ?",
			wantArgs:  []any{10},
		},
		{
			name: "Test_Offset",
			args: args{
				options: options.TableOption{
					Offset: 5,
				},
			},
			wantQuery: " OFFSET ?",
			wantArgs:  []any{5},
		},
		{
			name: "Test_AllOptions",
			args: args{
				options: options.TableOption{
					Filters: []options.ColumnOption{
						{Column: "col1", Value: "val1"},
					},
					OrderBy: "col2 ASC",
					Limit:   20,
					Offset:  10,
				},
			},
			wantQuery: "WHERE col1 = ? ORDER BY col2 ASC LIMIT ? OFFSET ?",
			wantArgs:  []any{"val1", 20, 10},
		},
		{
			name: "Test_NoOptions",
			args: args{
				options: options.TableOption{},
			},
			wantQuery: "",
			wantArgs:  []any{},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			gotQuery, gotArgs := buildQueries(tt.args.options)
			if gotQuery != tt.wantQuery {
				t.Errorf("buildQueries() gotQuery = %v, %v", gotQuery, tt.wantQuery)
			}
			if !reflect.DeepEqual(gotArgs, tt.wantArgs) {
				t.Errorf("buildQueries() gotArgs = %v, %v", gotArgs, tt.wantArgs)
			}
		})
	}
}
