package ii

import (
	"fmt"
	"regexp"

	"golib/v2/features/mo"
)

func (c *ItemInfo) init() error {
	if err := c.initEnums(); err != nil {
		return err
	}
	if err := c.initValue(); err != nil {
		return err
	}
	if err := c.initPattern(); err != nil {
		return err
	}
	c.initMap()
	return c.initFieldMap()
}

// initFieldMap 创建字段索引
func (c *ItemInfo) initFieldMap() error {
	c.FieldMap = make(map[string]int)

	for i, field := range c.Fields {
		if !isEnabledType(field.Type) {
			return fmt.Errorf("%s: unenabled type: %s", c.Name, field.Type.String())
		}
		if field.Type == mo.TypeObject ||
			(field.Type == mo.TypeArray && field.Items == FieldItemsObject && !field.NoField) {
			if !field.NoField {
				if len(field.Fields) == 0 {
					return fmt.Errorf("%s: %s: object type must be set Field", c.Name, field.Name)
				}
				for _, sf := range field.Fields {
					if sf.Type == 0 {
						return fmt.Errorf("%s: %s.%s must be set Type", c.Name, field.Name, sf.Name)
					}
					if sf.Type == mo.TypeObject {
						return fmt.Errorf("%s: %s.%s can bot must be %s", c.Name, field.Name, sf.Name, sf.Type.String())
					}
				}
			}
		}
		for _, l := range field.Lookup {
			if l.ForeignField == "" || l.From == "" || l.AS == "" {
				return fmt.Errorf("%s: %s.Lookup: config error", c.Name, field.Name)
			}
			if l.AS == field.Name {
				return fmt.Errorf("%s: duplicate names are not allowed: Field.Name: %s, Lookup.AS: %s", c.Name, field.Name, l.AS)
			}
		}
		if len(field.Lookup) > 0 && len(field.Fields) == 0 {
			return fmt.Errorf("%s: %s.Lookup: must be set Field in Fields, because has Lookup", c.Name, field.Name)
		}
		for _, s := range field.Set {
			if s.Name == "" || s.OP == "" || s.Value == "" {
				return fmt.Errorf("%s: %s.Set: config error", c.Name, field.Name)
			}
		}
		c.FieldMap[field.Name] = i
	}
	return nil
}

// initEnums 初始化枚举类型值
func (c *ItemInfo) initEnums() error {
	for i, field := range c.Fields {
		length := len(field.Enums)
		enum := make([]any, length)
		for j := 0; j < length; j++ {
			val, err := field.Convert(field.Enums[j])
			if err != nil {
				return fmt.Errorf("%s.%s: initEnums: %s", c.Name, field.Name, err)
			}
			enum[j] = val
		}
		c.Fields[i].enums = enum
	}
	return nil
}

// initValue 初始化默认值类型
func (c *ItemInfo) initValue() error {
	for i, field := range c.Fields {
		c.Fields[i].defaultValue = field.Type.Default() // 先使用默认类型初始化
		if field.Default == "" {
			continue
		}
		switch field.Type {
		case mo.TypeObjectID:
			if field.Default == "new" {
				c.Fields[i].defaultValue = field.Default // 特殊处理
			}
		case mo.TypeDateTime:
			if field.Default == "now" {
				c.Fields[i].defaultValue = field.Default // 特殊处理
			}
		default:
			val, err := field.Convert(field.Default)
			if err != nil {
				return fmt.Errorf("%s.%s: initValue: %s", c.Name, field.Name, err)
			}
			c.Fields[i].defaultValue = val
		}
	}
	return nil
}

func (c *ItemInfo) initPattern() error {
	for i, field := range c.Fields {
		if field.Pattern != "" {
			regex, err := regexp.Compile(field.Pattern)
			if err != nil {
				return fmt.Errorf("%s.%s: initPattern: %s", c.Name, field.Name, err)
			}
			c.Fields[i].pattern = regex
		}
	}
	return nil
}

// initMap 初始化必填和唯一
func (c *ItemInfo) initMap() {
	c.RequiredMap = make(map[string]int)
	c.UniqueMap = make(map[string]int)
	for idx, field := range c.Fields {
		if field.Required {
			c.RequiredMap[field.Name] = idx
		}
		if field.Unique {
			c.UniqueMap[field.Name] = idx
		}
	}
}
