package cluster

import (
	"context"

	"github.com/pingcap/errcode"
	"github.com/pingcap/errors"
	"github.com/tidbcloud/metrics-server/central/db/dbutil"
	"github.com/tidbcloud/metrics-server/central/db/entity"
	"github.com/tidbcloud/metrics-server/central/db/tenant"
	"github.com/tidbcloud/pkgv2/log"
	"go.uber.org/zap"
)

type ModelV2 struct {
	log *zap.Logger
}

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

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

type UserContextV2 struct {
	ModelV2
	tenantAndUser *tenant.User
	log           *zap.Logger
}

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

func (c UserContextV2) CheckOrgIDAndProjectID(orgID, projectID entity.ID) error {
	user := c.tenantAndUser
	if user.IsImpersonated {
		return nil
	}

	if orgID != user.TenantID {
		return errcode.NewForbiddenErr(errors.New("org_id parameter is inconsistent with the user's org ID"))
	}

	return dbutil.CheckProjectID(user.Projects, projectID)
}
