package zapx

import (
	"fmt"
	"time"
)

// OperateRecord 结构表示操作记录。
type OperateRecord struct {
	EventTime   time.Time          `json:"eventTime"`   // 操作发生时间。非 go 客户端需要注意时间字符串的时区解析问题，类似 "+0000" 的时区格式是不支持的。
	Category    string             `json:"category"`    // 服务分类。用于区分不同服务的操作记录。比如 "tax"，"tax_v2"。
	UserId      string             `json:"userId"`      // 操作用户。可能不是一个 id 而是个代号，比如 "admin"，"system" 等。
	Entity      string             `json:"entity"`      // 操作的实体。如订单，账户，商品等。
	Action      string             `json:"action"`      // 动作。比如创建，删除，更新，或者更具体一点的支付，退款，发货等。
	Target      string             `json:"target"`      // 操作的对象，通常是对应数据的 id。可为空字符串。
	StringExtra map[string]string  `json:"stringExtra"` // 字符串型额外参数，比如订单对象的状态。
	FloatExtra  map[string]float64 `json:"floatExtra"`  // 浮点型额外参数，比如账户当前的余额。
	IntExtra    map[string]int32   `json:"intExtra"`    // 整数型额外参数，比如子对象的 id。
	BoolExtra   map[string]bool    `json:"boolExtra"`   // 布尔型额外参数，比如是否为某个特殊情况。
}

// Validate 校验参数
func (v OperateRecord) Validate() error {
	if v.EventTime.IsZero() {
		return ValidateError("时间不能为空")
	}
	if v.Category == "" {
		return ValidateError("服务分类不能为空")
	}
	if v.UserId == "" {
		return ValidateError("操作用户不能为空")
	}
	if v.Entity == "" {
		return ValidateError("操作实体不能为空")
	}
	if v.Action == "" {
		return ValidateError("动作不能为空")
	}
	mp := make(map[string]string)
	for k := range v.StringExtra {
		mp[k] = "字符串"
	}
	for k := range v.FloatExtra {
		if t, ok := mp[k]; ok {
			return ValidateError(fmt.Sprintf("参数重复定义，%s 已定义为 %s", k, t))
		}
		mp[k] = "浮点数"
	}
	for k := range v.IntExtra {
		if t, ok := mp[k]; ok {
			return ValidateError(fmt.Sprintf("参数重复定义，%s 已定义为 %s", k, t))
		}
		mp[k] = "整数"
	}
	for k := range v.BoolExtra {
		if t, ok := mp[k]; ok {
			return ValidateError(fmt.Sprintf("参数重复定义，%s 已定义为 %s", k, t))
		}
	}
	return nil
}

// ListOperationRequest 获取操作记录列表参数
type ListOperationRequest struct {
	Begin        time.Time           `json:"begin"`        // 开始时间。必填。
	End          time.Time           `json:"end"`          // 结束时间。必填。
	Category     string              `json:"category"`     // 服务分类。必填。
	UserId       string              `json:"userId"`       // 用户 id。选填。精确匹配。
	EntityFilter []StringFieldFilter `json:"entityFilter"` // 实体。选填。
	ActionFilter []StringFieldFilter `json:"actionFilter"` // 动作。选填。
	TargetFilter []StringFieldFilter `json:"targetFIlter"` // 目标。选填。
	StringFilter []StringFilter      `json:"stringFilter"` // 扩展参数。选填。
	FloatFilter  []FloatFilter       `json:"floatFilter"`  // 扩展参数。选填。
	IntFilter    []IntFilter         `json:"intFilter"`    // 扩展参数。选填。
	BoolFilter   []BoolFilter        `json:"boolFilter"`   // 扩展参数。选填。
	Order        string              `json:"order"`        // 排序类型。选填。默认倒序。
	PageNumber   int                 `json:"pageNumber"`   // 页码。必填。从 1 开始
	PageSize     int                 `json:"pageSize"`     // 每页数量。必填。
}

// Validate 校验参数
func (v ListOperationRequest) Validate() error {
	if v.Begin.IsZero() {
		return ValidateError("开始时间不能为空")
	}
	if v.End.IsZero() {
		return ValidateError("结束时间不能为空")
	}
	if v.Category == "" {
		return ValidateError("服务分类不能为空")
	}
	for _, f := range v.EntityFilter {
		err := f.Validate()
		if err != nil {
			return err
		}
	}
	for _, f := range v.ActionFilter {
		err := f.Validate()
		if err != nil {
			return err
		}
	}
	for _, f := range v.TargetFilter {
		err := f.Validate()
		if err != nil {
			return err
		}
	}
	for _, f := range v.StringFilter {
		err := f.Validate()
		if err != nil {
			return err
		}
	}
	for _, f := range v.FloatFilter {
		err := f.Validate()
		if err != nil {
			return err
		}
	}
	for _, f := range v.IntFilter {
		err := f.Validate()
		if err != nil {
			return err
		}
	}
	for _, f := range v.BoolFilter {
		err := f.Validate()
		if err != nil {
			return err
		}
	}
	if v.Order != "" && v.Order != OrderAsc && v.Order != OrderDesc {
		return ValidateError("排序类型错误")
	}
	if v.PageNumber < 1 {
		return ValidateError("页码不能小于 1")
	}
	if v.PageSize < 0 {
		return ValidateError("每页数量不能小于 0")
	}
	return nil
}

// ListOperationResponse 获取操作记录列表响应
type ListOperationResponse struct {
	Total int             `json:"total"` // 数据同条数
	List  []OperateRecord `json:"list"`  // 记录列表
}
