package holo

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"testing"
	"time"
)

func TestPostgres(t *testing.T) {
	dsn := "postgres://rec:test123456@11.158.166.161/mydb?sslmode=disable"
	psql := &Postgres{
		DSN: dsn,
	}

	err := psql.Init()
	if err != nil {
		t.Error(err)
	}
	query := "select count(*) from test"

	stmt, err := psql.DB.Prepare(query)
	if err != nil {
		t.Error(err)
	}
	rows, err := stmt.Query()
	if err != nil {
		t.Error(err)
	}
	defer stmt.Close()
	defer rows.Close()
	var count int

	for rows.Next() {
		if err := rows.Scan(&count); err != nil {
			t.Error(err)
		}

		fmt.Println("rows count:", count)

	}

}

func TestPostgresSelect(t *testing.T) {
	dsn := "postgres://LTAIm398VwCMfDhK:vFNt9TQTQTlbzwtzlIH4HTegWHqJrw@hgpostcn-cn-st21oucpr001-cn-beijing.hologres.aliyuncs.com:80/mydb?sslmode=disable"
	psql := &Postgres{
		DSN: dsn,
	}

	err := psql.Init()
	if err != nil {
		t.Error(err)
	}
	query := "select * from t_test where id=1"

	stmt, err := psql.DB.Prepare(query)
	if err != nil {
		t.Error(err)
	}
	rows, err := stmt.Query()
	if err != nil {
		t.Error(err)
	}
	defer stmt.Close()
	defer rows.Close()

	columns, err := rows.ColumnTypes()
	if err != nil {
		t.Error(err)
	}
	values := make([]interface{}, len(columns))
	for i, column := range columns {
		fmt.Println(column.Name(), column.ScanType())
		switch column.ScanType().Kind() {
		case reflect.Int32:
			// values[i] = reflect.New(sql.NullInt32).Interface()
			values[i] = &sql.NullInt32{}
		case reflect.Bool:
			// values[i] = reflect.New(sql.NullInt32).Interface()
			values[i] = &sql.NullBool{}
		case reflect.String:
			values[i] = &sql.NullString{}
		default:
			values[i] = &sql.NullFloat64{}
		}
		// values[i] = reflect.New(column.ScanType()).Interface()
	}
	fmt.Println(columns)
	for rows.Next() {
		if err := rows.Scan(values...); err == nil {
			for i, column := range columns {
				name := column.Name()
				nullable, ok := column.Nullable()
				if ok && nullable {
					continue
				}

				val := values[i]
				switch v := val.(type) {
				case *sql.NullInt32:
					if v.Valid {
						fmt.Println(name, "int valid", v.Int32)
					}

				case string:
					f, err := strconv.ParseFloat(v, 64)
					fmt.Println(name, v, f, err)
				default:
					fmt.Println("default", name, v)
				}
			}
		} else {
			t.Error(err)
		}
	}

}
func TestPostgresConnection(t *testing.T) {
	dsn := "postgres://LTAIm398VwCMfDhK:vFNt9TQTQTlbzwtzlIH4HTegWHqJrw@hgpostcn-cn-st21oucpr001-cn-beijing.hologres.aliyuncs.com:80/mydb?sslmode=disable"
	psql := &Postgres{
		DSN: dsn,
	}

	err := psql.Init()
	if err != nil {
		t.Error(err)
	}

	conn, err := psql.DB.Conn(context.Background())
	if err != nil {
		t.Error(err)
	}
	query := "select val from t_test2 where id=%d"

	for i := 1; i < 4; i++ {
		go func(i int) {
			sqlquery := fmt.Sprintf(query, i)
			for {
				rows, err := conn.QueryContext(context.Background(), sqlquery)
				if err != nil {
					t.Error(err)
				}

				fmt.Println(sqlquery, rows, err)
				for rows.Next() {
					var v int
					if err := rows.Scan(&v); err == nil {
						if v != i {
							fmt.Println(i, v)
							t.Error(errors.New("query error"))
						}
					}
				}
				rows.Close()
			}
		}(i)
	}

	time.Sleep(time.Minute)
}
