package tenant

import (
	"context"
	"fmt"
	"strings"

	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	"github.com/tidbcloud/devops/entity/event"
	tntent "github.com/tidbcloud/devops/entity/tenant"
	"github.com/tidbcloud/devops/pkg/infra/log"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
	"github.com/tidbcloud/devops/pkg/service/tenant/region"
)

func (s *svc) HandleDBaasTenantEvent(uuid string, ev *event.TenantEvent) error {
	ctx := s.WrapContext(context.Background())
	log.FromContext(ctx).Info("handle dbaas tenant event", "uuid", uuid, "event", ev)

	accountTenant, err := s.accountCli.GetTenant(ctx, ev.OrgId)
	if err != nil {
		return fmt.Errorf("get tenant from account service failed: %s", err)
	}

	originalTenant, err := s.tenantRepo.Load(ctx, ev.OrgId)
	if err == nil {
		if ev.OrgEventType == event.OrgEventTypeCreate {
			log.FromContext(ctx).Info("tenant already exists", "uuid", uuid, "event", ev)
			return nil
		} else if ev.OrgEventType == event.OrgEventTypeDelete {
			originalTenant.Status = tntent.TenantStatus(accountTenant.Status)
		} else {
			originalTenant.Status = tntent.TenantStatus(accountTenant.Status)
			originalTenant.Name = accountTenant.Name
			originalTenant.Email = accountTenant.Email
			originalTenant.Country = accountTenant.Country
			originalTenant.TimeZone = accountTenant.TimeZone
			originalTenant.Kind = tntent.TenantKind(accountTenant.Kind)
			originalTenant.CountryRegion = region.CountryToRegion(strings.ToUpper(accountTenant.Country))
		}

		if err := s.tenantRepo.Save(ctx, originalTenant); err != nil {
			return err
		}
	} else {
		if err := s.tenantRepo.Save(ctx, accountTenantToEntity(accountTenant)); err != nil {
			return err
		}
	}

	log.FromContext(ctx).Info("handle tenant success", "uuid", uuid, "event", ev)
	return nil
}

func (s *svc) HandleDBaasTenantPlanEvent(uuid string, ev *event.TenantPlanEvent) error {
	ctx := s.WrapContext(context.Background())
	log.FromContext(ctx).Info("handle dbaas tenant plan event", "uuid", uuid, "event", ev)
	tenant, err := s.tenantRepo.Load(ctx, ev.TenantID)
	if err != nil {
		return err
	}
	tenant.Plan = tntent.TenantPlan(ev.EffectivePlan)
	if err := s.tenantRepo.Save(ctx, tenant); err != nil {
		return err
	}
	return nil
}

func accountTenantToEntity(accountTenant *account.Org) *tntent.Tenant {
	return &tntent.Tenant{
		Id:            accountTenant.Id,
		Name:          accountTenant.Name,
		Status:        tntent.TenantStatus(accountTenant.Status),
		Email:         accountTenant.Email,
		CreatedAt:     pointer.Pointer(accountTenant.CreatedAt.AsTime()),
		Country:       accountTenant.Country,
		TimeZone:      accountTenant.TimeZone,
		Kind:          tntent.TenantKind(accountTenant.Kind),
		Plan:          tntent.TenantPlan(accountTenant.Plan),
		CountryRegion: region.CountryToRegion(strings.ToUpper(accountTenant.Country)),
	}
}
