package task

import (
	"gorm.io/gorm"

	"github.com/pingcap-inc/clinic/pkg/db"
	"github.com/pingcap-inc/clinic/pkg/ngm/performance_insight/service"
)

func fetchCreatedOrFailedTasks() ([]db.PerformanceInsightTask, error) {
	var tasks []db.PerformanceInsightTask
	err := db.Transaction(func(tx *gorm.DB) error {
		q := tx.Debug().Model(&db.PerformanceInsightTask{}).
			Preload("PerformanceInsightCluster").
			Preload("PerformanceInsightCluster.Cluster").
			Preload("PerformanceInsightCluster.Cluster.Organization").
			Where("performance_insight_tasks.status IN (?)", []string{service.TaskStatusCreated, service.TaskStatusFailed})

		// Do query.
		return q.Find(&tasks).Error
	})
	if err != nil {
		return nil, err
	}
	return tasks, nil
}

func overwriteRunningTasks() error {
	err := db.Transaction(func(tx *gorm.DB) error {
		q := tx.Debug().Model(&db.PerformanceInsightTask{}).
			Where("status = ?", service.TaskStatusRunning).
			Updates(map[string]any{
				"status": service.TaskStatusCreated,
			})
		return q.Error
	})
	if err != nil {
		return err
	}
	return nil
}

func writeFailedStatus(taskID uint, message string) error {
	err := db.Transaction(func(tx *gorm.DB) error {
		q := tx.Debug().Model(&db.PerformanceInsightTask{}).
			Where("id = ?", taskID).
			Updates(map[string]any{
				"status":              service.TaskStatusFailed,
				"last_failed_message": message,
			})
		return q.Error
	})
	if err != nil {
		return err
	}
	return nil
}

func writeSucceededStatus(taskID, materialCount uint) error {
	err := db.Transaction(func(tx *gorm.DB) error {
		q := tx.Debug().Model(&db.PerformanceInsightTask{}).
			Where("id = ?", taskID).
			Updates(map[string]any{
				"status":         service.TaskStatusSucceeded,
				"material_count": materialCount,
			})
		return q.Error
	})
	if err != nil {
		return err
	}
	return nil
}

func writeRunningTaskStatus(taskID uint) error {
	err := db.Transaction(func(tx *gorm.DB) error {
		q := tx.Debug().Model(&db.PerformanceInsightTask{}).
			Where("id = ?", taskID).
			Updates(map[string]any{
				"status":          service.TaskStatusRunning,
				"execution_count": gorm.Expr("execution_count + ?", 1),
			})
		return q.Error
	})
	if err != nil {
		return err
	}
	return nil
}

func writeResults(results any) error {
	err := db.Transaction(func(tx *gorm.DB) error {
		q := tx.Debug().Create(results)
		return q.Error
	})
	if err != nil {
		return err
	}
	return nil
}
