// Package systemconfig 提供受控系统配置的超级管理员读取投影。
package systemconfig

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/infrastructure/systemconfig"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
)

// ListQuery 按模块分页查询代码注册配置和未注册遗留记录。
type ListQuery struct {
	reader *systemconfig.Reader
}

// NewListQuery 创建系统配置列表查询。
func NewListQuery(reader *systemconfig.Reader) *ListQuery {
	return &ListQuery{reader: reader}
}

// Execute 执行超级管理员系统配置查询。
func (q *ListQuery) Execute(ctx context.Context, request dto.SystemConfigListRequest) (*dto.SystemConfigListResponse, error) {
	if middleware.GetUserTypeFromContext(ctx) != constants.UserTypeSuperAdmin {
		return nil, errors.New(errors.CodeForbidden)
	}
	page := request.Page
	if page <= 0 {
		page = 1
	}
	pageSize := request.PageSize
	if pageSize <= 0 {
		pageSize = constants.DefaultPageSize
	}
	if pageSize > constants.MaxPageSize {
		pageSize = constants.MaxPageSize
	}
	items, err := q.reader.List(ctx, request.Module)
	if err != nil {
		return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询系统配置失败")
	}
	total := len(items)
	start := (page - 1) * pageSize
	if start > total {
		start = total
	}
	end := start + pageSize
	if end > total {
		end = total
	}
	result := make([]dto.SystemConfigItem, 0, end-start)
	for _, item := range items[start:end] {
		value := item.Value
		if item.Definition.Sensitive && value != "" {
			value = "[已配置]"
		}
		projection := dto.SystemConfigItem{
			ConfigKey: item.Definition.Key, Value: value, ValueType: item.Definition.ValueType,
			Module: item.Definition.Module, Description: item.Definition.Description,
			Readonly: item.Definition.Readonly || !item.Registered, Sensitive: item.Definition.Sensitive,
			Registered: item.Registered, Control: item.Definition.Control,
			EnumValues: item.Definition.EnumValues, Min: item.Definition.Min, Max: item.Definition.Max,
		}
		if item.Record != nil {
			updatedAt := item.Record.UpdatedAt
			projection.UpdatedAt = &updatedAt
		}
		result = append(result, projection)
	}
	return &dto.SystemConfigListResponse{List: result, Total: int64(total), Page: page, PageSize: pageSize}, nil
}
