package service

import (
	"context"
	"sync"

	"github.com/samber/lo"
	"github.com/tidbcloud/account/idl/pbgen/proto/account"
)

type MockAccountSvc struct {
	account.UnimplementedAccountAPIServiceServer

	name string
	orgs map[uint64]map[uint64]*account.Project
	lock sync.Mutex
}

func NewMockAccountSvc(name string) *MockAccountSvc {
	return &MockAccountSvc{
		name: name,
		orgs: make(map[uint64]map[uint64]*account.Project),
	}
}

func (svc *MockAccountSvc) Reset() {
	svc.lock.Lock()
	defer svc.lock.Unlock()
	svc.orgs = make(map[uint64]map[uint64]*account.Project)
}

func (svc *MockAccountSvc) CreateProjects(orgId, projectId uint64) {
	svc.lock.Lock()
	defer svc.lock.Unlock()
	projects, ok := svc.orgs[orgId]
	if !ok {
		projects = make(map[uint64]*account.Project)
	}
	projects[projectId] = &account.Project{
		TenantId: orgId,
		Id:       projectId,
	}
	svc.orgs[orgId] = projects
}

func (svc *MockAccountSvc) ListProjects(
	ctx context.Context,
	in *account.ProjectFilter,
) (*account.ListProjectsResponse, error) {
	svc.lock.Lock()
	defer svc.lock.Unlock()
	resp := &account.ListProjectsResponse{}
	for orgId, projects := range svc.orgs {
		if len(in.OrgIds) != 0 && !lo.Contains(in.OrgIds, orgId) {
			continue
		}
		for projectId, project := range projects {
			if len(in.Ids) != 0 && !lo.Contains(in.Ids, projectId) {
				continue
			}
			resp.Projects = append(resp.Projects, project)
		}
	}
	return resp, nil
}

func (svc *MockAccountSvc) ListProjectsByOrgs(
	ctx context.Context,
	in *account.ListProjectsByOrgsRequest,
) (*account.ListProjectsByOrgsResponse, error) {
	svc.lock.Lock()
	defer svc.lock.Unlock()
	resp := &account.ListProjectsByOrgsResponse{}
	for orgId, projects := range svc.orgs {
		if !lo.Contains(in.OrgIds, orgId) {
			continue
		}
		orgProjects := &account.OrgProject{
			OrgId: orgId,
		}
		for _, project := range projects {
			orgProjects.Projects = append(orgProjects.Projects, project)
		}
		resp.Projects = append(resp.Projects, orgProjects)
	}
	return resp, nil
}
