package service

import (
	"context"
	"fmt"
	"strings"

	"oci-portal/internal/model"
	"oci-portal/internal/oci"
)

// homeRegionOf 返回配置的 home region 名称；本地表查不到时退回默认区域。
// 用户管理等 IAM 写操作必须发往 home region。
func homeRegionOf(cfg *model.OciConfig) string {
	if info, ok := oci.RegionByKey(cfg.HomeRegionKey); ok {
		return info.Name
	}
	return cfg.Region
}

// credentialsAndHomeRegion 一次取回凭据与 home region。
func (s *OciConfigService) credentialsAndHomeRegion(ctx context.Context, id uint) (oci.Credentials, string, error) {
	cfg, err := s.Get(ctx, id)
	if err != nil {
		return oci.Credentials{}, "", err
	}
	cred, err := s.credentialsOf(cfg)
	if err != nil {
		return oci.Credentials{}, "", err
	}
	return cred, homeRegionOf(cfg), nil
}

// IdentityDomains 列出租户全部 ACTIVE 身份域(域选择器数据源)。
func (s *OciConfigService) IdentityDomains(ctx context.Context, id uint) ([]oci.IdentityDomain, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return nil, err
	}
	return s.client.ListIdentityDomains(ctx, cred, homeRegion)
}

// TenantUsers 列出租户 IAM 用户;domainID 非空只列该身份域。
func (s *OciConfigService) TenantUsers(ctx context.Context, id uint, domainID string) ([]oci.TenantUser, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return nil, err
	}
	return s.client.ListTenantUsers(ctx, cred, homeRegion, domainID)
}

// TenantUserDetail 查用户的域档案与管理员状态（编辑表单预填充用）。
func (s *OciConfigService) TenantUserDetail(ctx context.Context, id uint, domainID, userID string) (oci.TenantUserDetail, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.TenantUserDetail{}, err
	}
	return s.client.GetTenantUserDetail(ctx, cred, homeRegion, domainID, userID)
}

// CreateTenantUser 新增用户；名字与姓氏必填（域用户档案要求），
// 描述缺省用「名 姓」。
func (s *OciConfigService) CreateTenantUser(ctx context.Context, id uint, domainID string, in oci.CreateTenantUserInput) (oci.TenantUser, error) {
	if strings.TrimSpace(in.Name) == "" {
		return oci.TenantUser{}, fmt.Errorf("create tenant user: name is required")
	}
	if strings.TrimSpace(in.GivenName) == "" || strings.TrimSpace(in.FamilyName) == "" {
		return oci.TenantUser{}, fmt.Errorf("create tenant user: givenName and familyName are required")
	}
	if in.Description == "" {
		in.Description = strings.TrimSpace(in.GivenName + " " + in.FamilyName)
	}
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.TenantUser{}, err
	}
	return s.client.CreateTenantUser(ctx, cred, homeRegion, domainID, in)
}

// UpdateTenantUser 编辑用户资料；nil 字段不修改，全 nil 报错。
func (s *OciConfigService) UpdateTenantUser(ctx context.Context, id uint, domainID, userID string, in oci.UpdateTenantUserInput) (oci.TenantUser, error) {
	hasField := in.Description != nil || in.Email != nil || in.GivenName != nil || in.FamilyName != nil
	hasAdmin := in.GrantDomainAdmin != nil || in.AddToAdminGroup != nil
	if !hasField && !hasAdmin {
		return oci.TenantUser{}, fmt.Errorf("update tenant user: nothing to update")
	}
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.TenantUser{}, err
	}
	return s.client.UpdateTenantUser(ctx, cred, homeRegion, domainID, userID, in)
}

// IdentitySetting 读取域身份设置（当前只透出主邮箱必填开关）。
func (s *OciConfigService) IdentitySetting(ctx context.Context, id uint, domainID string) (oci.IdentitySettingInfo, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.IdentitySettingInfo{}, err
	}
	return s.client.GetIdentitySetting(ctx, cred, homeRegion, domainID)
}

// UpdateIdentitySetting 修改「用户需要提供主电子邮件地址」开关。
func (s *OciConfigService) UpdateIdentitySetting(ctx context.Context, id uint, domainID string, primaryEmailRequired bool) (oci.IdentitySettingInfo, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.IdentitySettingInfo{}, err
	}
	return s.client.UpdateIdentitySetting(ctx, cred, homeRegion, domainID, primaryEmailRequired)
}

// DeleteTenantUser 删除 IAM 用户；拒绝删除当前配置正在使用的用户。
func (s *OciConfigService) DeleteTenantUser(ctx context.Context, id uint, domainID, userID string) error {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return err
	}
	if userID == cred.UserOCID {
		return fmt.Errorf("delete tenant user: refusing to delete the user this config signs requests with")
	}
	return s.client.DeleteTenantUser(ctx, cred, homeRegion, domainID, userID)
}

// ResetTenantUserPassword 重置用户控制台密码，返回一次性新密码。
func (s *OciConfigService) ResetTenantUserPassword(ctx context.Context, id uint, domainID, userID string) (string, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return "", err
	}
	return s.client.ResetTenantUserPassword(ctx, cred, homeRegion, domainID, userID)
}

// DeleteTenantUserMfa 清除用户全部 MFA，返回删除的经典 TOTP 设备数。
func (s *OciConfigService) DeleteTenantUserMfa(ctx context.Context, id uint, domainID, userID string) (int, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return 0, err
	}
	return s.client.DeleteTenantUserMfaDevices(ctx, cred, homeRegion, domainID, userID)
}

// DeleteTenantUserApiKeys 删除用户的 API Key；默认保留当前配置使用的指纹。
func (s *OciConfigService) DeleteTenantUserApiKeys(ctx context.Context, id uint, userID string, includeCurrent bool) (int, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return 0, err
	}
	return s.client.DeleteTenantUserApiKeys(ctx, cred, homeRegion, userID, includeCurrent)
}

// NotificationRecipients 查询域通知收件人设置。
func (s *OciConfigService) NotificationRecipients(ctx context.Context, id uint, domainID string) (oci.NotificationRecipients, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.NotificationRecipients{}, err
	}
	return s.client.GetNotificationRecipients(ctx, cred, homeRegion, domainID)
}

// UpdateNotificationRecipients 把域通知改为只发给指定收件人；
// 收件人为空表示关闭 test mode 恢复默认发送。
func (s *OciConfigService) UpdateNotificationRecipients(ctx context.Context, id uint, domainID string, emails []string) (oci.NotificationRecipients, error) {
	if err := validateEmails(emails); err != nil {
		return oci.NotificationRecipients{}, err
	}
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.NotificationRecipients{}, err
	}
	return s.client.UpdateNotificationRecipients(ctx, cred, homeRegion, domainID, emails)
}

func validateEmails(emails []string) error {
	for _, email := range emails {
		if !strings.Contains(email, "@") || strings.ContainsAny(email, " \t") {
			return fmt.Errorf("update notification recipients: invalid email %q", email)
		}
	}
	return nil
}

// PasswordPolicies 列出域密码策略。
func (s *OciConfigService) PasswordPolicies(ctx context.Context, id uint, domainID string) ([]oci.PasswordPolicyInfo, error) {
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return nil, err
	}
	return s.client.ListPasswordPolicies(ctx, cred, homeRegion, domainID)
}

// UpdatePasswordPolicy 修改域密码策略的过期天数或最小长度。
func (s *OciConfigService) UpdatePasswordPolicy(ctx context.Context, id uint, domainID, policyID string, in oci.UpdatePasswordPolicyInput) (oci.PasswordPolicyInfo, error) {
	if in.PasswordExpiresAfter == nil && in.MinLength == nil {
		return oci.PasswordPolicyInfo{}, fmt.Errorf("update password policy: nothing to update")
	}
	cred, homeRegion, err := s.credentialsAndHomeRegion(ctx, id)
	if err != nil {
		return oci.PasswordPolicyInfo{}, err
	}
	return s.client.UpdatePasswordPolicy(ctx, cred, homeRegion, domainID, policyID, in)
}
