// Package role 提供角色管理的业务逻辑服务
// 包含角色创建、查询、更新、删除、角色权限关联等功能
package role

import (
	"context"
	"fmt"
	"strings"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/store"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"gorm.io/gorm"
)

// Service 角色业务服务
type Service struct {
	roleStore           *postgres.RoleStore
	permissionStore     *postgres.PermissionStore
	rolePermissionStore *postgres.RolePermissionStore
}

// New 创建角色服务
func New(roleStore *postgres.RoleStore, permissionStore *postgres.PermissionStore, rolePermissionStore *postgres.RolePermissionStore) *Service {
	return &Service{
		roleStore:           roleStore,
		permissionStore:     permissionStore,
		rolePermissionStore: rolePermissionStore,
	}
}

// Create 创建角色
func (s *Service) Create(ctx context.Context, req *dto.CreateRoleRequest) (*model.Role, error) {
	// 获取当前用户 ID
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	// 创建角色
	role := &model.Role{
		RoleName: req.RoleName,
		RoleDesc: req.RoleDesc,
		RoleType: req.RoleType,
		Status:   constants.StatusEnabled,
	}

	if err := s.roleStore.Create(ctx, role); err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "创建角色失败")
	}

	return role, nil
}

// Get 获取角色
func (s *Service) Get(ctx context.Context, id uint) (*model.Role, error) {
	role, err := s.roleStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeRoleNotFound, "角色不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取角色失败")
	}
	return role, nil
}

// Update 更新角色
func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateRoleRequest) (*model.Role, error) {
	// 获取当前用户 ID
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	// 获取现有角色
	role, err := s.roleStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeRoleNotFound, "角色不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取角色失败")
	}

	// 更新字段
	if req.RoleName != nil {
		role.RoleName = *req.RoleName
	}
	if req.RoleDesc != nil {
		role.RoleDesc = *req.RoleDesc
	}
	if req.Status != nil {
		role.Status = *req.Status
	}

	role.Updater = currentUserID

	if err := s.roleStore.Update(ctx, role); err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "更新角色失败")
	}

	return role, nil
}

// Delete 软删除角色
func (s *Service) Delete(ctx context.Context, id uint) error {
	// 检查角色存在
	_, err := s.roleStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeRoleNotFound, "角色不存在")
		}
		return errors.Wrap(errors.CodeInternalError, err, "获取角色失败")
	}

	if err := s.roleStore.Delete(ctx, id); err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "删除角色失败")
	}

	return nil
}

// List 查询角色列表
func (s *Service) List(ctx context.Context, req *dto.RoleListRequest) ([]*model.Role, int64, error) {
	opts := &store.QueryOptions{
		Page:     req.Page,
		PageSize: req.PageSize,
		OrderBy:  "id DESC",
	}
	if opts.Page == 0 {
		opts.Page = 1
	}
	if opts.PageSize == 0 {
		opts.PageSize = constants.DefaultPageSize
	}

	filters := make(map[string]interface{})
	if req.RoleName != "" {
		filters["role_name"] = req.RoleName
	}
	if req.RoleType != nil {
		filters["role_type"] = *req.RoleType
	}
	if req.Status != nil {
		filters["status"] = *req.Status
	}

	return s.roleStore.List(ctx, opts, filters)
}

// AssignPermissions 为角色分配权限
func (s *Service) AssignPermissions(ctx context.Context, roleID uint, permIDs []uint) ([]*model.RolePermission, error) {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	role, err := s.roleStore.GetByID(ctx, roleID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeRoleNotFound, "角色不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取角色失败")
	}

	permissions, err := s.permissionStore.GetByIDs(ctx, permIDs)
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取权限失败")
	}

	if len(permissions) != len(permIDs) {
		return nil, errors.New(errors.CodePermissionNotFound, "部分权限不存在")
	}

	roleTypeStr := fmt.Sprintf("%d", role.RoleType)
	var invalidPermIDs []uint
	for _, perm := range permissions {
		if !contains(perm.AvailableForRoleTypes, roleTypeStr) {
			invalidPermIDs = append(invalidPermIDs, perm.ID)
		}
	}

	if len(invalidPermIDs) > 0 {
		return nil, errors.New(errors.CodeInvalidParam, fmt.Sprintf("权限 %v 不适用于此角色类型", invalidPermIDs))
	}

	var rps []*model.RolePermission
	for _, permID := range permIDs {
		exists, _ := s.rolePermissionStore.Exists(ctx, roleID, permID)
		if exists {
			continue
		}

		rp := &model.RolePermission{
			RoleID: roleID,
			PermID: permID,
			Status: constants.StatusEnabled,
		}
		if err := s.rolePermissionStore.Create(ctx, rp); err != nil {
			return nil, errors.Wrap(errors.CodeInternalError, err, "创建角色-权限关联失败")
		}
		rps = append(rps, rp)
	}

	return rps, nil
}

// GetPermissions 获取角色的所有权限
func (s *Service) GetPermissions(ctx context.Context, roleID uint) ([]*model.Permission, error) {
	// 检查角色存在
	_, err := s.roleStore.GetByID(ctx, roleID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeRoleNotFound, "角色不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取角色失败")
	}

	// 获取权限 ID 列表
	permIDs, err := s.rolePermissionStore.GetPermIDsByRoleID(ctx, roleID)
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取角色权限 ID 失败")
	}

	if len(permIDs) == 0 {
		return []*model.Permission{}, nil
	}

	// 获取权限详情
	return s.permissionStore.GetByIDs(ctx, permIDs)
}

// RemovePermission 移除角色的权限
func (s *Service) RemovePermission(ctx context.Context, roleID, permID uint) error {
	_, err := s.roleStore.GetByID(ctx, roleID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeRoleNotFound, "角色不存在")
		}
		return errors.Wrap(errors.CodeInternalError, err, "获取角色失败")
	}

	if err := s.rolePermissionStore.Delete(ctx, roleID, permID); err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "删除角色-权限关联失败")
	}

	return nil
}

// UpdateStatus 更新角色状态
func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	role, err := s.roleStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeRoleNotFound, "角色不存在")
		}
		return errors.Wrap(errors.CodeInternalError, err, "获取角色失败")
	}

	role.Status = status
	role.Updater = currentUserID

	if err := s.roleStore.Update(ctx, role); err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "更新角色状态失败")
	}

	return nil
}

func contains(availableForRoleTypes, roleTypeStr string) bool {
	types := strings.Split(availableForRoleTypes, ",")
	for _, t := range types {
		if strings.TrimSpace(t) == roleTypeStr {
			return true
		}
	}
	return false
}
