package service

import (
	"fmt"
	"strings"
	"time"

	"github.com/veypi/vbase/internal/cache"
	"github.com/veypi/vbase/internal/model"
)

// PermissionChecker 权限检查器
type PermissionChecker struct{}

// NewPermissionChecker 创建权限检查器
func NewPermissionChecker() *PermissionChecker {
	return &PermissionChecker{}
}

// CheckResult 检查结果
type CheckResult struct {
	Allowed bool   `json:"allowed"`
	Reason  string `json:"reason,omitempty"`
}

// Check 检查权限
// 支持两种模式：
// 1. 组织上下文权限 (orgID != "")：检查用户在组织内的角色和权限
// 2. 个人上下文权限 (orgID == "")：检查用户的系统级权限和个人资源权限
func (pc *PermissionChecker) Check(userID, orgID, resource, action string, resourceData map[string]any) (*CheckResult, error) {
	// 1. 检查缓存
	if cache.IsEnabled() {
		allowed, cached, err := cache.GetPermission(userID, orgID, resource, action)
		if err == nil && cached {
			return &CheckResult{Allowed: allowed}, nil
		}
	}

	// 2. 根据是否有组织上下文选择检查方式
	if orgID != "" {
		// 组织上下文：检查组织相关权限
		return pc.checkOrgPermission(userID, orgID, resource, action, resourceData)
	}

	// 3. 无组织上下文：检查个人/系统级权限
	return pc.checkPersonalPermission(userID, resource, action, resourceData)
}

// checkOrgPermission 检查组织上下文权限
func (pc *PermissionChecker) checkOrgPermission(userID, orgID, resource, action string, resourceData map[string]any) (*CheckResult, error) {
	// 2.1 检查是否是组织所有者（拥有所有权限）
	var org model.Org
	if err := model.DB.First(&org, "id = ?", orgID).Error; err == nil {
		if org.OwnerID == userID {
			pc.cacheResult(userID, orgID, resource, action, true)
			return &CheckResult{Allowed: true, Reason: "organization owner"}, nil
		}
	}

	// 2.2 获取用户在该组织的角色
	var member model.OrgMember
	if err := model.DB.Where("org_id = ? AND user_id = ? AND status = ?", orgID, userID, model.MemberStatusActive).First(&member).Error; err != nil {
		// 用户不在组织中
		pc.cacheResult(userID, orgID, resource, action, false)
		return &CheckResult{Allowed: false, Reason: "not a member of organization"}, nil
	}

	// 2.3 获取角色关联的策略
	roleIDs := parseRoles(member.RoleIDs)
	if len(roleIDs) == 0 {
		pc.cacheResult(userID, orgID, resource, action, false)
		return &CheckResult{Allowed: false, Reason: "no roles assigned"}, nil
	}

	var roles []model.Role
	if err := model.DB.Where("id IN ?", roleIDs).Find(&roles).Error; err != nil {
		return nil, err
	}

	// 2.4 收集所有策略ID
	policyIDMap := make(map[string]bool)
	for _, role := range roles {
		ids := parseRoles(role.PolicyIDs)
		for _, id := range ids {
			policyIDMap[id] = true
		}
	}

	if len(policyIDMap) == 0 {
		pc.cacheResult(userID, orgID, resource, action, false)
		return &CheckResult{Allowed: false, Reason: "no policies assigned"}, nil
	}

	policyIDs := make([]string, 0, len(policyIDMap))
	for id := range policyIDMap {
		policyIDs = append(policyIDs, id)
	}

	// 2.5 获取策略详情
	var policies []model.Policy
	if err := model.DB.Where("id IN ?", policyIDs).Find(&policies).Error; err != nil {
		return nil, err
	}

	// 2.6 评估策略
	allowed := pc.evaluatePolicies(policies, userID, orgID, resource, action, resourceData)
	pc.cacheResult(userID, orgID, resource, action, allowed)

	if allowed {
		return &CheckResult{Allowed: true}, nil
	}
	return &CheckResult{Allowed: false, Reason: "policy denied"}, nil
}

// checkPersonalPermission 检查个人/系统级权限（无组织上下文）
func (pc *PermissionChecker) checkPersonalPermission(userID, resource, action string, resourceData map[string]any) (*CheckResult, error) {
	// 3.1 检查是否是资源所有者
	// 对于个人资源（如自己的用户信息），允许操作
	if resourceData != nil {
		if ownerID, ok := resourceData["owner_id"].(string); ok && ownerID == userID {
			pc.cacheResult(userID, "", resource, action, true)
			return &CheckResult{Allowed: true, Reason: "resource owner"}, nil
		}
		if createdBy, ok := resourceData["created_by"].(string); ok && createdBy == userID {
			pc.cacheResult(userID, "", resource, action, true)
			return &CheckResult{Allowed: true, Reason: "resource creator"}, nil
		}
	}

	// 3.2 加载系统级默认策略
	// 无组织用户可以执行的操作：管理自己的数据
	policies := pc.getDefaultPersonalPolicies()

	// 3.3 评估策略
	allowed := pc.evaluatePolicies(policies, userID, "", resource, action, resourceData)
	pc.cacheResult(userID, "", resource, action, allowed)

	if allowed {
		return &CheckResult{Allowed: true}, nil
	}
	return &CheckResult{Allowed: false, Reason: "personal policy denied"}, nil
}

// getDefaultPersonalPolicies 获取个人默认策略
// 无组织用户默认可以管理自己的资源
func (pc *PermissionChecker) getDefaultPersonalPolicies() []model.Policy {
	return []model.Policy{
		{
			Code:      "personal:user:read:own",
			Resource:  "user",
			Action:    "read",
			Effect:    model.EffectAllow,
			Condition: "owner",
		},
		{
			Code:      "personal:user:update:own",
			Resource:  "user",
			Action:    "update",
			Effect:    model.EffectAllow,
			Condition: "owner",
		},
		{
			Code:      "personal:user:delete:own",
			Resource:  "user",
			Action:    "delete",
			Effect:    model.EffectAllow,
			Condition: "owner",
		},
		{
			Code:      "personal:binding:manage",
			Resource:  "binding",
			Action:    "*",
			Effect:    model.EffectAllow,
			Condition: "",
		},
		{
			Code:      "personal:org:create",
			Resource:  "org",
			Action:    "create",
			Effect:    model.EffectAllow,
			Condition: "",
		},
		{
			Code:      "personal:org:read:own",
			Resource:  "org",
			Action:    "read",
			Effect:    model.EffectAllow,
			Condition: "owner",
		},
	}
}

// evaluatePolicies 评估策略
func (pc *PermissionChecker) evaluatePolicies(policies []model.Policy, userID, orgID, resource, action string, resourceData map[string]any) bool {
	// 先处理deny策略
	for _, p := range policies {
		if p.Effect != model.EffectDeny {
			continue
		}
		if pc.matchPolicy(&p, resource, action) {
			// 检查条件
			if pc.evaluateCondition(&p, userID, orgID, resourceData) {
				return false
			}
		}
	}

	// 再处理allow策略
	for _, p := range policies {
		if p.Effect != model.EffectAllow {
			continue
		}
		if pc.matchPolicy(&p, resource, action) {
			if pc.evaluateCondition(&p, userID, orgID, resourceData) {
				return true
			}
		}
	}

	return false
}

// matchPolicy 匹配策略资源和方法
func (pc *PermissionChecker) matchPolicy(p *model.Policy, resource, action string) bool {
	// 资源匹配
	if p.Resource != "*" && p.Resource != resource {
		return false
	}
	// 动作匹配
	if p.Action != "*" && p.Action != action {
		return false
	}
	return true
}

// evaluateCondition 评估条件
func (pc *PermissionChecker) evaluateCondition(p *model.Policy, userID, orgID string, resourceData map[string]any) bool {
	condition := p.Condition
	if condition == "" || condition == "true" {
		return true
	}

	// 简单条件评估
	switch condition {
	case "owner":
		// 检查是否是资源所有者
		if ownerID, ok := resourceData["owner_id"].(string); ok {
			return ownerID == userID
		}
		if createdBy, ok := resourceData["created_by"].(string); ok {
			return createdBy == userID
		}
		return false
	case "org_member":
		// 检查是否是组织成员
		if orgID == "" {
			return false
		}
		var count int64
		model.DB.Model(&model.OrgMember{}).Where("org_id = ? AND user_id = ? AND status = ?", orgID, userID, model.MemberStatusActive).Count(&count)
		return count > 0
	default:
		// 其他复杂条件暂时返回true
		return true
	}
}

// cacheResult 缓存结果
func (pc *PermissionChecker) cacheResult(userID, orgID, resource, action string, allowed bool) {
	if cache.IsEnabled() {
		cache.SetPermission(userID, orgID, resource, action, allowed, 1*time.Minute)
	}
}

// GetUserPermissions 获取用户的所有权限
func (pc *PermissionChecker) GetUserPermissions(userID, orgID string) ([]string, error) {
	// 获取用户角色
	var member model.OrgMember
	if err := model.DB.Where("org_id = ? AND user_id = ? AND status = ?", orgID, userID, model.MemberStatusActive).First(&member).Error; err != nil {
		return []string{}, nil
	}

	roleIDs := parseRoles(member.RoleIDs)
	if len(roleIDs) == 0 {
		return []string{}, nil
	}

	var roles []model.Role
	if err := model.DB.Where("id IN ?", roleIDs).Find(&roles).Error; err != nil {
		return nil, err
	}

	// 收集策略
	policyIDMap := make(map[string]bool)
	for _, role := range roles {
		ids := parseRoles(role.PolicyIDs)
		for _, id := range ids {
			policyIDMap[id] = true
		}
	}

	if len(policyIDMap) == 0 {
		return []string{}, nil
	}

	policyIDs := make([]string, 0, len(policyIDMap))
	for id := range policyIDMap {
		policyIDs = append(policyIDs, id)
	}

	var policies []model.Policy
	if err := model.DB.Where("id IN ?", policyIDs).Find(&policies).Error; err != nil {
		return nil, err
	}

	// 格式化权限
	perms := make([]string, 0, len(policies))
	for _, p := range policies {
		if p.Effect == model.EffectAllow {
			perms = append(perms, fmt.Sprintf("%s:%s", p.Resource, p.Action))
		}
	}

	return perms, nil
}

// ClearUserPermissionCache 清除用户权限缓存
func ClearUserPermissionCache(userID string) {
	if cache.IsEnabled() {
		cache.DeleteUserPermissions(userID)
	}
}

// ClearOrgPermissionCache 清除组织权限缓存
func ClearOrgPermissionCache(orgID string) {
	if cache.IsEnabled() {
		cache.DeleteOrgPermissions(orgID)
	}
}

func parseRoles(roleIDs string) []string {
	if roleIDs == "" {
		return []string{}
	}
	return strings.Split(roleIDs, ",")
}

// InitPermissionChecker 初始化权限检查器
var InitPermissionChecker = NewPermissionChecker()
