package system

import (
	"context"

	"kra/internal/biz/system"
	"kra/internal/server/middleware"
	types "kra/internal/service/types/system"

	"github.com/go-kratos/kratos/v2/errors"
	"github.com/go-kratos/kratos/v2/transport/http"
)

// AuthorityService 角色服务
type AuthorityService struct {
	uc     *system.AuthorityUsecase
	casbin system.CasbinRepo
}

// NewAuthorityService 创建角色服务
func NewAuthorityService(uc *system.AuthorityUsecase, casbin system.CasbinRepo) *AuthorityService {
	return &AuthorityService{
		uc:     uc,
		casbin: casbin,
	}
}

// AuthorityInfo 角色信息
type AuthorityFullInfo struct {
	AuthorityId     uint                   `json:"authorityId"`
	AuthorityName   string                 `json:"authorityName"`
	ParentId        *uint                  `json:"parentId,omitempty"`
	DefaultRouter   string                 `json:"defaultRouter"`
	DataAuthorityId []*types.AuthorityInfo `json:"dataAuthorityId,omitempty"`
	Children        []*AuthorityFullInfo   `json:"children,omitempty"`
}

// CreateAuthorityRequest 创建角色请求
type CreateAuthorityRequest struct {
	AuthorityId   uint   `json:"authorityId"`
	AuthorityName string `json:"authorityName"`
	ParentId      uint   `json:"parentId"`
	DefaultRouter string `json:"defaultRouter"`
}

// CreateAuthority 创建角色
func (s *AuthorityService) CreateAuthority(ctx context.Context, req *CreateAuthorityRequest) (*AuthorityFullInfo, error) {
	auth := &system.Authority{
		AuthorityId:   req.AuthorityId,
		AuthorityName: req.AuthorityName,
		DefaultRouter: req.DefaultRouter,
	}
	if req.ParentId != 0 {
		auth.ParentId = &req.ParentId
	}

	result, err := s.uc.CreateAuthority(ctx, auth)
	if err != nil {
		return nil, err
	}

	// 刷新Casbin
	_ = s.casbin.FreshCasbin()

	return toAuthorityFullInfo(result), nil
}

// CopyAuthorityRequest 复制角色请求
type CopyAuthorityRequest struct {
	Authority      CreateAuthorityRequest `json:"authority"`
	OldAuthorityId uint                   `json:"oldAuthorityId"`
}

// CopyAuthority 复制角色
func (s *AuthorityService) CopyAuthority(ctx context.Context, adminAuthorityID uint, req *CopyAuthorityRequest) (*AuthorityFullInfo, error) {
	newAuth := &system.Authority{
		AuthorityId:   req.Authority.AuthorityId,
		AuthorityName: req.Authority.AuthorityName,
		DefaultRouter: req.Authority.DefaultRouter,
	}
	if req.Authority.ParentId != 0 {
		newAuth.ParentId = &req.Authority.ParentId
	}

	result, err := s.uc.CopyAuthority(ctx, adminAuthorityID, req.OldAuthorityId, newAuth)
	if err != nil {
		return nil, err
	}

	return toAuthorityFullInfo(result), nil
}

// UpdateAuthorityRequest 更新角色请求
type UpdateAuthorityRequest struct {
	AuthorityId   uint   `json:"authorityId"`
	AuthorityName string `json:"authorityName"`
	ParentId      uint   `json:"parentId"`
	DefaultRouter string `json:"defaultRouter"`
}

// UpdateAuthority 更新角色
func (s *AuthorityService) UpdateAuthority(ctx context.Context, req *UpdateAuthorityRequest) (*AuthorityFullInfo, error) {
	auth := &system.Authority{
		AuthorityId:   req.AuthorityId,
		AuthorityName: req.AuthorityName,
		DefaultRouter: req.DefaultRouter,
	}
	if req.ParentId != 0 {
		auth.ParentId = &req.ParentId
	}

	result, err := s.uc.UpdateAuthority(ctx, auth)
	if err != nil {
		return nil, err
	}

	return toAuthorityFullInfo(result), nil
}

// DeleteAuthority 删除角色
func (s *AuthorityService) DeleteAuthority(ctx context.Context, authorityId uint) error {
	if err := s.uc.DeleteAuthority(ctx, authorityId); err != nil {
		return err
	}

	// 刷新Casbin
	_ = s.casbin.FreshCasbin()

	return nil
}

// GetAuthorityList 获取角色列表
func (s *AuthorityService) GetAuthorityList(ctx context.Context, authorityId uint) ([]*AuthorityFullInfo, error) {
	list, err := s.uc.GetAuthorityInfoList(ctx, authorityId)
	if err != nil {
		return nil, err
	}

	return toAuthorityFullInfoList(list), nil
}

// SetDataAuthorityRequest 设置角色资源权限请求
type SetDataAuthorityRequest struct {
	AuthorityId      uint   `json:"authorityId"`
	DataAuthorityIds []uint `json:"dataAuthorityId"`
}

// SetDataAuthority 设置角色资源权限
func (s *AuthorityService) SetDataAuthority(ctx context.Context, adminAuthorityID uint, req *SetDataAuthorityRequest) error {
	return s.uc.SetDataAuthority(ctx, adminAuthorityID, req.AuthorityId, req.DataAuthorityIds)
}

// 转换函数
func toAuthorityFullInfo(auth *system.Authority) *AuthorityFullInfo {
	info := &AuthorityFullInfo{
		AuthorityId:   auth.AuthorityId,
		AuthorityName: auth.AuthorityName,
		ParentId:      auth.ParentId,
		DefaultRouter: auth.DefaultRouter,
	}
	return info
}

func toAuthorityFullInfoList(list []*system.AuthorityFull) []*AuthorityFullInfo {
	result := make([]*AuthorityFullInfo, len(list))
	for i, auth := range list {
		result[i] = &AuthorityFullInfo{
			AuthorityId:   auth.AuthorityId,
			AuthorityName: auth.AuthorityName,
			ParentId:      auth.ParentId,
			DefaultRouter: auth.DefaultRouter,
			Children:      toAuthorityFullInfoList(auth.Children),
		}
		// DataAuthorityId
		if len(auth.DataAuthorityId) > 0 {
			result[i].DataAuthorityId = make([]*types.AuthorityInfo, len(auth.DataAuthorityId))
			for j, da := range auth.DataAuthorityId {
				result[i].DataAuthorityId[j] = &types.AuthorityInfo{
					AuthorityId:   da.AuthorityId,
					AuthorityName: da.AuthorityName,
					ParentId:      da.ParentId,
					DefaultRouter: da.DefaultRouter,
				}
			}
		}
	}
	return result
}

// RegisterRoutes 注册路由
func (s *AuthorityService) RegisterRoutes(rg *RouterGroup) {
	// 私有路由 + 操作记录（写操作）
	rg.PrivateWithRecord.POST("/authority/createAuthority", s.handleCreateAuthority)
	rg.PrivateWithRecord.POST("/authority/copyAuthority", s.handleCopyAuthority)
	rg.PrivateWithRecord.PUT("/authority/updateAuthority", s.handleUpdateAuthority)
	rg.PrivateWithRecord.POST("/authority/deleteAuthority", s.handleDeleteAuthority)
	rg.PrivateWithRecord.POST("/authority/setDataAuthority", s.handleSetDataAuthority)

	// 私有路由（读操作，不记录）
	rg.Private.POST("/authority/getAuthorityList", s.handleGetAuthorityList)
}

// HTTP Handlers
func (s *AuthorityService) handleCreateAuthority(ctx http.Context) error {
	var req CreateAuthorityRequest
	if err := ctx.Bind(&req); err != nil {
		return err
	}
	resp, err := s.CreateAuthority(ctx, &req)
	if err != nil {
		return errors.BadRequest("CREATE_FAILED", err.Error())
	}
	return ctx.Result(200, map[string]any{"code": 0, "msg": "创建成功", "data": map[string]any{"authority": resp}})
}

func (s *AuthorityService) handleCopyAuthority(ctx http.Context) error {
	var req CopyAuthorityRequest
	if err := ctx.Bind(&req); err != nil {
		return err
	}
	adminAuthorityID := middleware.GetAuthorityID(ctx)
	resp, err := s.CopyAuthority(ctx, adminAuthorityID, &req)
	if err != nil {
		return errors.BadRequest("COPY_FAILED", err.Error())
	}
	return ctx.Result(200, map[string]any{"code": 0, "msg": "复制成功", "data": map[string]any{"authority": resp}})
}

func (s *AuthorityService) handleUpdateAuthority(ctx http.Context) error {
	var req UpdateAuthorityRequest
	if err := ctx.Bind(&req); err != nil {
		return err
	}
	resp, err := s.UpdateAuthority(ctx, &req)
	if err != nil {
		return errors.BadRequest("UPDATE_FAILED", err.Error())
	}
	return ctx.Result(200, map[string]any{"code": 0, "msg": "更新成功", "data": map[string]any{"authority": resp}})
}

func (s *AuthorityService) handleDeleteAuthority(ctx http.Context) error {
	var req struct {
		AuthorityId uint `json:"authorityId"`
	}
	if err := ctx.Bind(&req); err != nil {
		return err
	}
	if err := s.DeleteAuthority(ctx, req.AuthorityId); err != nil {
		return errors.BadRequest("DELETE_FAILED", err.Error())
	}
	return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
}

func (s *AuthorityService) handleGetAuthorityList(ctx http.Context) error {
	authorityId := middleware.GetAuthorityID(ctx)
	resp, err := s.GetAuthorityList(ctx, authorityId)
	if err != nil {
		return errors.InternalServer("LIST_ERROR", err.Error())
	}
	return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"list": resp}})
}

func (s *AuthorityService) handleSetDataAuthority(ctx http.Context) error {
	var req SetDataAuthorityRequest
	if err := ctx.Bind(&req); err != nil {
		return err
	}
	adminAuthorityID := middleware.GetAuthorityID(ctx)
	if err := s.SetDataAuthority(ctx, adminAuthorityID, &req); err != nil {
		return errors.BadRequest("SET_FAILED", err.Error())
	}
	return ctx.Result(200, map[string]any{"code": 0, "msg": "设置成功"})
}
