package applogic

import (
	"context"
	"fmt"

	"aijianzhan/platform/internal/authx"
	"aijianzhan/platform/internal/rolestore"
	"aijianzhan/platform/internal/svc"
	"aijianzhan/platform/internal/tenantperm"
	"aijianzhan/platform/internal/types"
)

type RoleAdminLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewRoleAdminLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RoleAdminLogic {
	return &RoleAdminLogic{ctx: ctx, svcCtx: svcCtx}
}

func (l *RoleAdminLogic) store() (rolestore.Store, error) {
	if l.svcCtx.Roles == nil {
		return nil, fmt.Errorf("role store unavailable")
	}
	return l.svcCtx.Roles, nil
}

func (l *RoleAdminLogic) List() ([]rolestore.Role, error) {
	st, err := l.store()
	if err != nil {
		return nil, err
	}
	tid := authx.TenantID(l.ctx)
	_ = st.EnsureDefaults(l.ctx, tid)
	return st.List(l.ctx, tid)
}

func (l *RoleAdminLogic) Get(roleID int64) (*rolestore.Role, error) {
	st, err := l.store()
	if err != nil {
		return nil, err
	}
	return st.Get(l.ctx, authx.TenantID(l.ctx), roleID)
}

func (l *RoleAdminLogic) Create(req *types.RoleCreateReq) (*rolestore.Role, error) {
	st, err := l.store()
	if err != nil {
		return nil, err
	}
	perms := authx.NormalizePerms(req.Permissions)
	if err := tenantperm.MustAllow(l.ctx, l.svcCtx.TenantPerm, authx.TenantID(l.ctx), perms); err != nil {
		return nil, err
	}
	return st.Create(l.ctx, authx.TenantID(l.ctx), rolestore.CreateInput{
		Code:        req.Code,
		Name:        req.Name,
		Description: req.Description,
		Permissions: perms,
	})
}

func (l *RoleAdminLogic) Update(roleID int64, req *types.RoleUpdateReq) (*rolestore.Role, error) {
	st, err := l.store()
	if err != nil {
		return nil, err
	}
	in := rolestore.UpdateInput{}
	if req.Name != nil {
		in.Name = req.Name
	}
	if req.Description != nil {
		in.Description = req.Description
	}
	if req.Permissions != nil {
		perms := authx.NormalizePerms(*req.Permissions)
		if err := tenantperm.MustAllow(l.ctx, l.svcCtx.TenantPerm, authx.TenantID(l.ctx), perms); err != nil {
			return nil, err
		}
		in.Permissions = &perms
	}
	return st.Update(l.ctx, authx.TenantID(l.ctx), roleID, in)
}

func (l *RoleAdminLogic) Delete(roleID int64) error {
	st, err := l.store()
	if err != nil {
		return err
	}
	return st.Delete(l.ctx, authx.TenantID(l.ctx), roleID)
}
