package vercel

import (
	"context"
	serrors "errors"

	"github.com/pingcap/errors"
	"github.com/tidbcloud/pkgv2/tracing"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type BranchEnvironmentIdentifierDAO interface {
	AddEnvironmentIdentifier(ctx context.Context, identifier BranchEnvironmentIdentifier) error
	GetEnvironmentIdentifierByGitBranch(ctx context.Context, githubRepoID, gitBranchRef string, connID uint64) (identifier *BranchEnvironmentIdentifier, err error)
	GetEnvironmentIdentifiersByBranchID(ctx context.Context, branchID string) (identifier []BranchEnvironmentIdentifier, err error)
	DeleteEnvironmentIdentifier(ctx context.Context, id uint64) (err error)
}

type branchEnvironmentIdentifierDAOImpl struct {
	db *gorm.DB
}

func NewBranchEnvironmentIdentifierDAO(db *gorm.DB) BranchEnvironmentIdentifierDAO {
	return &branchEnvironmentIdentifierDAOImpl{
		db: db,
	}
}

func (d *branchEnvironmentIdentifierDAOImpl) AddEnvironmentIdentifier(ctx context.Context, identifier BranchEnvironmentIdentifier) (err error) {
	ctx, span := Tracer.Start(ctx, "branchEnvironmentIdentifierDAOImpl.AddEnvironmentIdentifier")
	defer func() {
		tracing.EndSpan(span, err)
	}()

	err = d.db.Create(&identifier).Error
	if err != nil {
		return errors.Trace(err)
	}

	tilog.Info(ctx, "Succeed to add branch identifier")
	return nil
}

func (d *branchEnvironmentIdentifierDAOImpl) GetEnvironmentIdentifierByGitBranch(ctx context.Context, githubRepoID, gitBranchRef string, connID uint64) (identifier *BranchEnvironmentIdentifier, err error) {
	_, span := Tracer.Start(ctx, "branchEnvironmentIdentifierDAOImpl.GetEnvironmentIdentifierByGitBranch")
	defer func() {
		tracing.EndSpan(span, err)
	}()

	err = d.db.Preload(clause.Associations).Preload("ClusterConnection."+clause.Associations).Where("github_repo_id = ? AND git_branch_ref = ? AND cluster_connection_id = ?", githubRepoID, gitBranchRef, connID).First(&identifier).Error
	if err != nil {
		if serrors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		} else {
			return nil, errors.Trace(err)
		}
	}

	return identifier, nil
}

func (d *branchEnvironmentIdentifierDAOImpl) GetEnvironmentIdentifiersByBranchID(ctx context.Context, branchID string) (identifier []BranchEnvironmentIdentifier, err error) {
	_, span := Tracer.Start(ctx, "branchEnvironmentIdentifierDAOImpl.GetEnvironmentIdentifiersByBranchID")
	defer func() {
		tracing.EndSpan(span, err)
	}()

	err = d.db.Preload(clause.Associations).Preload("ClusterConnection."+clause.Associations).Where("branch_id = ?", branchID).Find(&identifier).Error
	if err != nil {
		if serrors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		} else {
			return nil, errors.Trace(err)
		}
	}

	return identifier, nil
}

func (d *branchEnvironmentIdentifierDAOImpl) DeleteEnvironmentIdentifier(ctx context.Context, id uint64) (err error) {
	_, span := Tracer.Start(ctx, "branchEnvironmentIdentifierDAOImpl.DeleteEnvironmentIdentifier")
	defer func() {
		tracing.EndSpan(span, err)
	}()

	err = d.db.Delete(&BranchEnvironmentIdentifier{}, id).Error
	if err != nil {
		return errors.Trace(err)
	}

	tilog.Info(ctx, "Succeed to delete branch identifier")
	return nil
}
