package tenant

import (
	"context"
	"time"

	"github.com/pingcap/dbaas/central/db/entity"
	"github.com/pingcap/dbaas/central/grpc/grpcli"
	"github.com/pingcap/dbaas/central/service/cvt"
	"github.com/pingcap/dbaas/central/utils"
	"github.com/tidbcloud/idl/pbgen/proto/central"
	"github.com/tidbcloud/idl/pbgen/proto/core"
)

func (s *tenantService) CreateIamRole(ctx context.Context, req *central.CreateIamRoleReq) (*central.CreateIamRoleResp, error) {
	orgID := entity.ID(req.OrgId)
	projectID := entity.ID(req.ProjectId)
	userContext := s.userContext(ctx)

	err := userContext.CheckOrgIDAndProjectID(orgID, projectID)
	if err != nil {
		return nil, err
	}

	createIamRoleReq := &core.CreateIamRoleReq{
		ProjectId: projectID.Uint64(),
		RoleArn:   req.RoleArn,
		BaseReq:   nil,
	}
	createIamRoleResp, err := grpcli.CreateIamRole(ctx, createIamRoleReq)
	if err != nil {
		return nil, err
	}
	resp := &central.CreateIamRoleResp{
		BaseResp: &central.BaseResp{},
		Id:       createIamRoleResp.Id,
	}
	return resp, nil
}

func buildIamRoles(roles []*core.IamRole) []*central.IamRole {
	items := make([]*central.IamRole, len(roles))
	for i, role := range roles {
		createdAt := time.Unix(role.CreatedAt, 0)

		iamRole := &central.IamRole{
			Id:        role.Id,
			Arn:       role.Arn,
			CreatedAt: utils.MustTimestampProto(createdAt),
			Usages:    nil,
		}

		if role.Usages != nil {
			iamRole.Usages = make([]*central.IamRoleUsage, len(role.Usages))
			for j, usage := range role.Usages {
				iamRole.Usages[j] = &central.IamRoleUsage{
					ServiceName:  cvt.CoreIamRoleUsageServiceName2Central(usage.ServiceName),
					ProviderName: usage.ProviderName,
					RegionName:   usage.RegionName,
				}
			}
		}

		items[i] = iamRole
	}

	return items
}

func (s *tenantService) ListIamRoles(ctx context.Context, req *central.ListIamRolesReq) (*central.ListIamRolesResp, error) {
	orgID := entity.ID(req.OrgId)
	projectID := entity.ID(req.ProjectId)
	userContext := s.userContext(ctx)

	err := userContext.CheckOrgIDAndProjectID(orgID, projectID)
	if err != nil {
		return nil, err
	}

	listIamRolesReq := &core.ListIamRolesReq{
		Filter: &core.IamRoleFilter{
			ProjectIds: []uint64{projectID.Uint64()},
		},
		BaseReq: nil,
	}
	listIamRolesResp, err := grpcli.ListIamRoles(ctx, listIamRolesReq)
	if err != nil {
		return nil, err
	}
	roles := buildIamRoles(listIamRolesResp.Roles)

	resp := &central.ListIamRolesResp{
		Items:    roles,
		Total:    int32(len(roles)),
		BaseResp: &central.BaseResp{},
	}
	return resp, nil
}

func (s *tenantService) DeleteIamRole(ctx context.Context, req *central.DeleteIamRoleReq) (*central.DefaultResp, error) {
	orgID := entity.ID(req.OrgId)
	projectID := entity.ID(req.ProjectId)
	userContext := s.userContext(ctx)

	err := userContext.CheckOrgIDAndProjectID(orgID, projectID)
	if err != nil {
		return nil, err
	}

	deleteIamRoleReq := &core.DeleteIamRoleReq{
		RoleId:  req.Id,
		BaseReq: nil,
	}
	_, err = grpcli.DeleteIamRole(ctx, deleteIamRoleReq)
	if err != nil {
		return nil, err
	}
	resp := &central.DefaultResp{
		BaseResp: &central.BaseResp{},
	}
	return resp, nil
}
