package actions

import (
	"context"
	"strings"

	gitea_actions "code.gitea.io/gitea/models/actions"
	"code.gitea.io/gitea/models/db"
	"xorm.io/builder"
)

type FindVariablesOpts struct {
	db.ListOptions
	IDs     []int64
	RepoID  int64
	OwnerID int64 // it will be ignored if RepoID is set
	Name    string
}

func (opts FindVariablesOpts) ToConds() builder.Cond {
	cond := builder.NewCond()
	if len(opts.IDs) > 0 {
		if len(opts.IDs) == 1 {
			cond = cond.And(builder.Eq{"id": opts.IDs[0]})
		} else {
			cond = cond.And(builder.In("id", opts.IDs))
		}
	}

	// Since we now support instance-level variables,
	// there is no need to check for null values for `owner_id` and `repo_id`
	cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
	if opts.RepoID != 0 { // if RepoID is set
		// ignore OwnerID and treat it as 0
		cond = cond.And(builder.Eq{"owner_id": 0})
	} else {
		cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
	}

	if opts.Name != "" {
		cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
	}
	return cond
}

func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*gitea_actions.ActionVariable, error) {
	var variables []*gitea_actions.ActionVariable
	sess := db.GetEngine(ctx)
	if opts.PageSize != 0 {
		sess = db.SetSessionPagination(sess, &opts.ListOptions)
	}
	return variables, sess.Where(opts.ToConds()).OrderBy("created_unix desc").Find(&variables)
}

func CountVariables(ctx context.Context, opts FindVariablesOpts) (int64, error) {
	sess := db.GetEngine(ctx)
	return sess.Where(opts.ToConds()).Count(new(gitea_actions.ActionVariable))
}

func DeleteVariable(ctx context.Context, variable *gitea_actions.ActionVariable) error {
	if _, err := db.DeleteByID(ctx, variable.ID, variable); err != nil {
		return err
	}
	return nil
}
