//nolint:unused // skip for unstable test, for readability.
package worker

import (
	"context"
	"time"

	"github.com/go-logr/logr"
	"github.com/pingcap/errors"
	"github.com/tidbcloud/aws-shared-provider/tests/framework"
)

var _ worker = &analyzeWorker{}

const (
	analyzePollInterval = 10 * time.Second
	analyzePollTimeout  = 30 * time.Minute
)

type analyzeWorker struct {
	wctx   *workerContext
	logger logr.Logger

	tableID int64
}

func newAnalyzeWorker(f *framework.Framework, wctx *workerContext) *analyzeWorker {
	logger := f.Logger.WithName("analyze")
	return &analyzeWorker{
		wctx:   wctx,
		logger: logger,
	}
}

func (w *analyzeWorker) name() string {
	return "analyze"
}

func (w *analyzeWorker) updateTaskInfo(tableID int64) {
	w.tableID = tableID
}

func (w *analyzeWorker) triggerJob(ctx context.Context) error {
	sql := "create table test.analyze_t(a int, b int)"
	_, err := w.wctx.db.ExecContext(ctx, sql)
	if err != nil {
		return err
	}

	sql = `select tidb_table_id from information_schema.tables where table_schema = "test" and table_name = "analyze_t"`
	rows, err := w.wctx.db.QueryContext(ctx, sql)
	if err != nil {
		return err
	}
	if !rows.Next() {
		return errors.Errorf("unexpected result")
	}
	if rows.Err() != nil {
		return rows.Err()
	}
	var tableID int64
	err = rows.Scan(&tableID)
	if err != nil {
		return err
	}
	w.updateTaskInfo(tableID)

	_, err = w.wctx.db.ExecContext(ctx, `insert into test.analyze_t value(1, 2)`)
	if err != nil {
		return err
	}

	for i := 0; i < 10; i++ {
		_, err = w.wctx.db.ExecContext(ctx, `insert into test.analyze_t select * from test.analyze_t`)
		if err != nil {
			return err
		}
	}

	return nil
}

func (w *analyzeWorker) verifyJob(ctx context.Context) error {
	ticker := time.NewTicker(analyzePollInterval)
	timer := time.NewTicker(analyzePollTimeout)
	now := time.Now()

	defer func() {
		ticker.Stop()
		timer.Stop()
		w.logger.Info("verifyJob done", "takes", time.Since(now))
	}()
	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-ticker.C:
			sql := `select count(*) from mysql.auto_analyze_tasks_history where table_id = ?`
			rows, err := w.wctx.db.QueryContext(ctx, sql, w.tableID)
			if err != nil || !rows.Next() {
				continue
			}
			if rows.Err() != nil {
				return rows.Err()
			}
			var count int64
			err = rows.Scan(&count)
			if err != nil {
				return err
			}
			if count != 0 {
				return nil
			}
		case <-timer.C:
			return errors.Errorf("waiting for analyze job timeout")
		}
	}
}
