package tenant

import (
	"strings"

	"quyun/v2/app/errorx"
	"quyun/v2/app/http/tenant/dto"
	"quyun/v2/app/requests"
	"quyun/v2/app/services"
	"quyun/v2/database/models"
	"quyun/v2/pkg/consts"

	"github.com/gofiber/fiber/v3"
	log "github.com/sirupsen/logrus"
)

// tenantUserAdmin provides tenant-admin member management endpoints.
//
//	@provider
type tenantUserAdmin struct{}

// adminRemoveUser
//
//	@Summary	移除租户成员（租户管理）
//	@Tags		Tenant
//	@Accept		json
//	@Produce	json
//	@Param		tenantCode	path	string	true	"Tenant Code"
//	@Param		userID		path	int64	true	"UserID"
//	@Success	200			{object}	requests.Pager
//
//	@Router		/t/:tenantCode/v1/admin/users/:userID [delete]
//	@Bind		tenant local key(tenant)
//	@Bind		tenantUser local key(tenant_user)
//	@Bind		userID path
func (*tenantUserAdmin) adminRemoveUser(
	ctx fiber.Ctx,
	tenant *models.Tenant,
	tenantUser *models.TenantUser,
	userID int64,
) error {
	if err := requireTenantAdmin(tenantUser); err != nil {
		return err
	}
	if userID <= 0 {
		return errorx.ErrInvalidParameter.WithMsg("user_id must be > 0")
	}

	log.WithFields(log.Fields{
		"tenant_id":         tenant.ID,
		"operator_user_id":  tenantUser.UserID,
		"target_user_id":    userID,
		"operator_is_admin": true,
	}).Info("tenant.admin.users.remove")

	// 关键语义：删除成员接口幂等化；目标用户不属于租户时也返回成功，便于后台重试与批量操作。
	return services.Tenant.RemoveUser(ctx.Context(), tenant.ID, userID)
}

// adminJoinUser
//
//	@Summary	添加租户成员（租户管理）
//	@Tags		Tenant
//	@Accept		json
//	@Produce	json
//	@Param		tenantCode	path		string	true	"Tenant Code"
//	@Param		userID		path		int64	true	"UserID"
//	@Success	200			{object}	dto.AdminTenantUserJoinResponse
//
//	@Router		/t/:tenantCode/v1/admin/users/:userID/join [post]
//	@Bind		tenant local key(tenant)
//	@Bind		tenantUser local key(tenant_user)
//	@Bind		userID path
func (*tenantUserAdmin) adminJoinUser(
	ctx fiber.Ctx,
	tenant *models.Tenant,
	tenantUser *models.TenantUser,
	userID int64,
) (*dto.AdminTenantUserJoinResponse, error) {
	if err := requireTenantAdmin(tenantUser); err != nil {
		return nil, err
	}
	if userID <= 0 {
		return nil, errorx.ErrInvalidParameter.WithMsg("user_id must be > 0")
	}

	log.WithFields(log.Fields{
		"tenant_id":         tenant.ID,
		"operator_user_id":  tenantUser.UserID,
		"target_user_id":    userID,
		"operator_is_admin": true,
	}).Info("tenant.admin.users.join")

	// 关键逻辑：以 TenantUser 为准创建成员关系；服务层保证幂等（已存在则不重复创建）。
	if err := services.Tenant.AddUser(ctx.Context(), tenant.ID, userID); err != nil {
		return nil, err
	}

	m, err := services.Tenant.FindTenantUser(ctx.Context(), tenant.ID, userID)
	if err != nil {
		return nil, err
	}
	return &dto.AdminTenantUserJoinResponse{TenantUser: m}, nil
}

// adminSetUserRole
//
//	@Summary	设置成员角色（租户管理）
//	@Tags		Tenant
//	@Accept		json
//	@Produce	json
//	@Param		tenantCode	path		string							true	"Tenant Code"
//	@Param		userID		path		int64							true	"UserID"
//	@Param		form		body		dto.AdminTenantUserRoleUpdateForm	true	"Form"
//	@Success	200			{object}	dto.AdminTenantUserJoinResponse
//
//	@Router		/t/:tenantCode/v1/admin/users/:userID/role [patch]
//	@Bind		tenant local key(tenant)
//	@Bind		tenantUser local key(tenant_user)
//	@Bind		userID path
//	@Bind		form body
func (*tenantUserAdmin) adminSetUserRole(
	ctx fiber.Ctx,
	tenant *models.Tenant,
	tenantUser *models.TenantUser,
	userID int64,
	form *dto.AdminTenantUserRoleUpdateForm,
) (*dto.AdminTenantUserJoinResponse, error) {
	if err := requireTenantAdmin(tenantUser); err != nil {
		return nil, err
	}
	if userID <= 0 || form == nil {
		return nil, errorx.ErrInvalidParameter
	}

	roleStr := strings.TrimSpace(form.Role)
	if roleStr == "" {
		return nil, errorx.ErrInvalidParameter.WithMsg("role is required")
	}

	var role consts.TenantUserRole
	switch roleStr {
	case string(consts.TenantUserRoleMember):
		role = consts.TenantUserRoleMember
	case string(consts.TenantUserRoleTenantAdmin):
		role = consts.TenantUserRoleTenantAdmin
	default:
		return nil, errorx.ErrInvalidParameter.WithMsg("invalid role")
	}

	log.WithFields(log.Fields{
		"tenant_id":        tenant.ID,
		"operator_user_id": tenantUser.UserID,
		"target_user_id":   userID,
		"role":             role,
	}).Info("tenant.admin.users.set_role")

	if err := services.Tenant.SetUserRole(ctx.Context(), tenant.ID, userID, role); err != nil {
		return nil, err
	}

	m, err := services.Tenant.FindTenantUser(ctx.Context(), tenant.ID, userID)
	if err != nil {
		return nil, err
	}
	return &dto.AdminTenantUserJoinResponse{TenantUser: m}, nil
}

// adminTenantUsers
//
//	@Summary	成员列表（租户管理）
//	@Tags		Tenant
//	@Accept		json
//	@Produce	json
//	@Param		tenantCode	path		string						true	"Tenant Code"
//	@Param		filter		query		dto.AdminTenantUserListFilter	true	"Filter"
//	@Success	200			{object}	requests.Pager{items=dto.AdminTenantUserItem}
//
//	@Router		/t/:tenantCode/v1/admin/users [get]
//	@Bind		tenant local key(tenant)
//	@Bind		tenantUser local key(tenant_user)
//	@Bind		filter query
func (*tenantUserAdmin) adminTenantUsers(
	ctx fiber.Ctx,
	tenant *models.Tenant,
	tenantUser *models.TenantUser,
	filter *dto.AdminTenantUserListFilter,
) (*requests.Pager, error) {
	if err := requireTenantAdmin(tenantUser); err != nil {
		return nil, err
	}

	log.WithFields(log.Fields{
		"tenant_id": tenant.ID,
		"user_id":   tenantUser.UserID,
		"query_uid": filter.UserID,
		"role":      filter.Role,
		"status":    filter.Status,
		"username":  filter.UsernameTrimmed(),
	}).Info("tenant.admin.users.list")

	// 按 llm.txt 约束：HTTP 层不允许直接查询数据库，全部交由 services 层处理。
	return services.Tenant.AdminTenantUsersPage(ctx.Context(), tenant.ID, filter)
}
