package bootable

import (
	"encoding/json"
	"sync"

	"git.simanc.com/software/golib/v4/features/mo"
	"git.simanc.com/software/golib/v4/infra/ii"
)

func objectToStr(row mo.M) string {
	b, err := json.Marshal(row)
	if err != nil {
		return err.Error()
	}
	return string(b)
}

// handleRows 展开 itemInfo 字段数据类型为 mo.TypeObject 和 mo.TypeArray 的数据
// {"name": "123", "submap": {"name":111,"age":222}}
func handleRows(info *ii.ItemInfo, resp *Response, handler Handler) {
	var gr sync.WaitGroup
	gr.Add(len(resp.Rows))
	for _, row := range resp.Rows {
		go func(gr *sync.WaitGroup, row mo.M) {
			handleRow(info, row)
			if handler != nil {
				handler(info, row)
			}
			gr.Done()
		}(&gr, row)
	}
	gr.Wait()
}

func handleRow(info *ii.ItemInfo, row mo.M) {
	handleTypeDateTime(info, row)
	// handleTypeFloat(info, row)
	handleTypeArray(info, row)
	handleFieldLookup(info, row)
	handleTypeObject(info, row)
}

// handleTypeDateTime 当时间戳为 0 时, 改为空字符串
func handleTypeDateTime(info *ii.ItemInfo, row mo.M) {
	for _, field := range info.FieldType(mo.TypeDateTime) {
		oldValue, ok := row[field.Name].(mo.DateTime)
		if !ok {
			continue
		}
		if oldValue == 0 {
			row[field.Name] = ""
		}
	}
}

func handleTypeFloat(info *ii.ItemInfo, row mo.M) {
	for _, field := range info.FieldType(mo.TypeDouble) {
		if field.Decimal <= 0 {
			continue
		}
		oldValue, ok := row[field.Name].(float64)
		if !ok {
			continue
		}
		newValue, err := field.Convert(oldValue)
		if err == nil {
			row[field.Name] = newValue
		}
	}
}

func handleTypeObject(info *ii.ItemInfo, row mo.M) {
	for _, field := range info.FieldType(mo.TypeObject) {
		oldMap, ok := row[field.Name].(mo.M)
		if !ok {
			continue
		}
		for k, v := range oldMap {
			row[field.Name+"."+k] = v
		}
		row[field.Name] = objectToStr(oldMap)
	}
}

func handleTypeArray(info *ii.ItemInfo, row mo.M) {
	for _, field := range info.FieldType(mo.TypeArray) {
		if field.Items == ii.FieldItemsObject {
			oldList, ok := row[field.Name].(mo.A)
			if !ok {
				continue
			}
			for i := 0; i < len(oldList); i++ {
				oldMap, o := oldList[i].(mo.M)
				if !o {
					continue
				}
				for j := 0; j < len(field.Fields); j++ {
					if label := field.Fields[j].Label; label != "" {
						oldMap[field.Fields[j].Name+"."+ii.FieldLabel] = label
					}
				}
			}
		}
	}
}

func handleFieldLookup(info *ii.ItemInfo, row mo.M) {
	for _, field := range info.Fields {
		for _, look := range field.Lookup {
			oldList, ok := row[look.AS].(mo.A)
			if !ok {
				continue
			}
			if len(oldList) == 0 || look.List {
				continue // 仅 List == false 时才展开数据
			}
			// 使用 SubField 展开
			for _, sf := range field.Fields {
				row[field.Name+"."+look.AS+"."+sf.Name] = oldList[0].(mo.M)[sf.Name]
			}
			delete(row, look.AS) // 展开后删除 as
		}
	}
}
