// Package cluster encapsulates all cluster functionality
package cluster

import (
	"context"

	"github.com/pingcap/errcode"
	"github.com/pingcap/errors"
	"github.com/tidbcloud/dataflow-service/internal/db/entity"
	"github.com/tidbcloud/dataflow-service/pkg/account/accountdb"
	"github.com/tidbcloud/pkgv2/log"
	"go.uber.org/zap"
)

// Model is created with NewModel
type Model struct {
	log *zap.Logger
}

// NewModel returns a Model
func NewModel(log *zap.Logger) Model {
	return Model{
		log: log,
	}
}

// UserContext attaches a User to a Context.
// This helps audit the User
type UserContext struct {
	Model
	tenantAndUser *accountdb.User
	log           *zap.Logger
}

// User returns a UserContext
func (m Model) User(ctx context.Context, user *accountdb.User) UserContext {
	return UserContext{
		Model:         m,
		tenantAndUser: user,
		log: m.log.With(zap.Uint64("tenantID", user.TenantID),
			zap.Uint64("userID", user.ID), zap.String("module", "cluster")).With(log.FieldsFromContext(ctx)...),
	}
}

func (c UserContext) Log() *zap.Logger {
	return c.log
}

func (c UserContext) CheckOrgID(orgID entity.ID) error {
	if c.tenantAndUser.IsImpersonated {
		return nil
	}
	userTenantID := c.tenantAndUser.TenantID
	if orgID.Uint64() != userTenantID {
		return errcode.NewForbiddenErr(errors.New("org_id parameter is inconsistent with the user's org ID"))
	}
	return nil
}
