package v1

import (
	"context"
	"strconv"

	"github.com/casbin/casbin/v2"
	"github.com/marmotedu/errors"
	"github.com/pingcap-inc/pinsights/internal/apiserver/store"
	"github.com/pingcap-inc/pinsights/internal/pkg/code"
	v1 "github.com/pingcap-inc/pinsights/model/v1"
	"github.com/pingcap-inc/pinsights/pkg/log"
)

type DashboardSrv interface {
	List(ctx context.Context, e *casbin.Enforcer, authingID string) ([]*v1.Dashboard, error)
}

type dashboardService struct {
	store store.Factory
}

var _ DashboardSrv = (*dashboardService)(nil)

func newDashboard(srv *service) *dashboardService {
	return &dashboardService{store: srv.store}
}

func (d *dashboardService) List(ctx context.Context, e *casbin.Enforcer, authingID string) ([]*v1.Dashboard, error) {
	dbs, err := d.store.Dashboards().List(ctx)
	if err != nil {
		log.L(ctx).Errorf("List dashboard from storage failed: %s", err.Error())

		return nil, errors.WithCode(code.ErrDatabase, err.Error())
	}

	var res []*v1.Dashboard

	user, err := d.store.Users().GetByAnyID(ctx, authingID)
	if err != nil {
		log.L(ctx).Errorf("Get user info from storage failed when list dashboard: %s", err.Error())
	}

	for _, item := range dbs.Items {
		if item.PermissionLevel == 0 {
			res = append(res, item)
		} else if item.PermissionLevel != 0 {
			sub := "u_" + strconv.FormatUint(user.ID, 10)
			obj := "/dashboard/" + item.Slug
			ok, err := e.Enforce(sub, obj, "read")

			if err != nil {
				log.L(ctx).Errorf("Enforce fail (sub: %s, obj: %s): %s", sub, obj, err.Error())
			}

			if ok {
				res = append(res, item)
			}
		}
	}

	return res, nil
}
