package appconfig

import (
	"context"
	"fmt"
	"strings"

	"hyapp-admin-server/internal/appctx"
	"hyapp-admin-server/internal/integration/userclient"
)

const (
	organizationExpansionScene = "organization_role_expansion"
	managerOperationsScene     = "manager_operations"

	roleScopeCountry = "country"
	roleScopeRegion  = "region"
	roleScopeGlobal  = "global"
)

// RoleScopePolicyClient 是 Admin 到 user-service owner 的最小边界；后台不能直接写 user DB 配置表。
type RoleScopePolicyClient interface {
	GetRoleScopePolicy(ctx context.Context, req userclient.GetRoleScopePolicyRequest) (*userclient.RoleScopePolicy, error)
	UpdateRoleScopePolicies(ctx context.Context, req userclient.UpdateRoleScopePoliciesRequest) ([]userclient.RoleScopePolicy, error)
}

type RoleScopePoliciesConfig struct {
	AppCode                            string `json:"appCode"`
	OrganizationScope                  string `json:"organizationScope"`
	ManagerBaseScope                   string `json:"managerBaseScope"`
	ManagerExpandedScope               string `json:"managerExpandedScope"`
	ManagerRegionExpansionConfigurable bool   `json:"managerRegionExpansionConfigurable"`
	UpdatedAtMS                        int64  `json:"updatedAtMs"`
}

func (s *AppConfigService) GetRoleScopePoliciesConfig(ctx context.Context, appCode string, requestID string) (RoleScopePoliciesConfig, error) {
	if s == nil || s.roleScopePolicies == nil {
		return RoleScopePoliciesConfig{}, fmt.Errorf("role scope policy client is not configured")
	}
	organization, err := s.roleScopePolicies.GetRoleScopePolicy(ctx, userclient.GetRoleScopePolicyRequest{
		RequestID: requestID,
		Caller:    "hyapp-admin-server",
		Scene:     organizationExpansionScene,
	})
	if err != nil {
		return RoleScopePoliciesConfig{}, err
	}
	manager, err := s.roleScopePolicies.GetRoleScopePolicy(ctx, userclient.GetRoleScopePolicyRequest{
		RequestID: requestID,
		Caller:    "hyapp-admin-server",
		Scene:     managerOperationsScene,
	})
	if err != nil {
		return RoleScopePoliciesConfig{}, err
	}
	return roleScopePoliciesConfigFromPolicies(appCode, []userclient.RoleScopePolicy{*organization, *manager})
}

func (s *AppConfigService) UpdateRoleScopePoliciesConfig(ctx context.Context, appCode string, requestID string, request roleScopePoliciesConfigRequest) (RoleScopePoliciesConfig, error) {
	if s == nil || s.roleScopePolicies == nil {
		return RoleScopePoliciesConfig{}, fmt.Errorf("role scope policy client is not configured")
	}
	policies, err := roleScopePoliciesFromRequest(request)
	if err != nil {
		return RoleScopePoliciesConfig{}, err
	}
	stored, err := s.roleScopePolicies.UpdateRoleScopePolicies(ctx, userclient.UpdateRoleScopePoliciesRequest{
		RequestID: requestID,
		Caller:    "hyapp-admin-server",
		Policies:  policies,
	})
	if err != nil {
		return RoleScopePoliciesConfig{}, err
	}
	return roleScopePoliciesConfigFromPolicies(appCode, stored)
}

func roleScopePoliciesFromRequest(request roleScopePoliciesConfigRequest) ([]userclient.RoleScopePolicy, error) {
	organizationScope := normalizeRoleScope(request.OrganizationScope)
	if organizationScope != roleScopeRegion && organizationScope != roleScopeGlobal {
		return nil, fmt.Errorf("组织角色范围不正确")
	}
	managerBase := normalizeRoleScope(request.ManagerBaseScope)
	managerExpanded := normalizeRoleScope(request.ManagerExpandedScope)
	if !validManagerRoleScope(managerBase) || !validManagerRoleScope(managerExpanded) {
		return nil, fmt.Errorf("经理操作范围不正确")
	}
	if !request.ManagerRegionExpansionConfigurable && managerExpanded != managerBase {
		return nil, fmt.Errorf("关闭经理扩区开关时两个范围必须一致")
	}
	if request.ManagerRegionExpansionConfigurable && roleScopeRank(managerExpanded) < roleScopeRank(managerBase) {
		return nil, fmt.Errorf("经理扩展范围不能小于基础范围")
	}
	return []userclient.RoleScopePolicy{
		{
			Scene:         organizationExpansionScene,
			BaseScope:     organizationScope,
			ExpandedScope: organizationScope,
		},
		{
			Scene:                       managerOperationsScene,
			BaseScope:                   managerBase,
			ExpandedScope:               managerExpanded,
			RegionExpansionConfigurable: request.ManagerRegionExpansionConfigurable,
		},
	}, nil
}

func roleScopePoliciesConfigFromPolicies(appCode string, policies []userclient.RoleScopePolicy) (RoleScopePoliciesConfig, error) {
	config := RoleScopePoliciesConfig{AppCode: appctx.Normalize(appCode)}
	seen := make(map[string]struct{}, len(policies))
	for _, policy := range policies {
		scene := strings.ToLower(strings.TrimSpace(policy.Scene))
		switch scene {
		case organizationExpansionScene:
			config.OrganizationScope = normalizeRoleScope(policy.BaseScope)
			if (config.OrganizationScope != roleScopeRegion && config.OrganizationScope != roleScopeGlobal) || normalizeRoleScope(policy.ExpandedScope) != config.OrganizationScope || policy.RegionExpansionConfigurable {
				return RoleScopePoliciesConfig{}, fmt.Errorf("组织角色范围配置无效")
			}
		case managerOperationsScene:
			config.ManagerBaseScope = normalizeRoleScope(policy.BaseScope)
			config.ManagerExpandedScope = normalizeRoleScope(policy.ExpandedScope)
			config.ManagerRegionExpansionConfigurable = policy.RegionExpansionConfigurable
			if !validManagerRoleScope(config.ManagerBaseScope) || !validManagerRoleScope(config.ManagerExpandedScope) {
				return RoleScopePoliciesConfig{}, fmt.Errorf("经理操作范围配置无效")
			}
			if (!config.ManagerRegionExpansionConfigurable && config.ManagerExpandedScope != config.ManagerBaseScope) || (config.ManagerRegionExpansionConfigurable && roleScopeRank(config.ManagerExpandedScope) < roleScopeRank(config.ManagerBaseScope)) {
				return RoleScopePoliciesConfig{}, fmt.Errorf("经理扩展范围配置无效")
			}
		default:
			continue
		}
		seen[scene] = struct{}{}
		if policy.UpdatedAtMS > config.UpdatedAtMS {
			config.UpdatedAtMS = policy.UpdatedAtMS
		}
	}
	if _, ok := seen[organizationExpansionScene]; !ok {
		return RoleScopePoliciesConfig{}, fmt.Errorf("组织角色范围配置缺失")
	}
	if _, ok := seen[managerOperationsScene]; !ok {
		return RoleScopePoliciesConfig{}, fmt.Errorf("经理操作范围配置缺失")
	}
	return config, nil
}

func normalizeRoleScope(value string) string {
	return strings.ToLower(strings.TrimSpace(value))
}

func validManagerRoleScope(value string) bool {
	return value == roleScopeCountry || value == roleScopeRegion || value == roleScopeGlobal
}

func roleScopeRank(value string) int {
	switch value {
	case roleScopeCountry:
		return 1
	case roleScopeRegion:
		return 2
	case roleScopeGlobal:
		return 3
	default:
		return 0
	}
}
