package openai

func schemaObjectProperties(schema any) map[string]any {
	m, ok := schema.(map[string]any)
	if !ok {
		return nil
	}
	props, _ := m["properties"].(map[string]any)
	if len(props) > 0 {
		return props
	}
	for _, key := range []string{"oneOf", "anyOf", "allOf"} {
		for _, branch := range schemaBranches(m[key]) {
			if branchProps := schemaObjectProperties(branch); len(branchProps) > 0 {
				if props == nil {
					props = map[string]any{}
				}
				for propKey, propValue := range branchProps {
					props[propKey] = propValue
				}
			}
		}
	}
	return props
}

func schemaArrayItemSchema(schema any) any {
	m, ok := schema.(map[string]any)
	if !ok {
		return nil
	}
	if items, ok := m["items"]; ok {
		return items
	}
	for _, key := range []string{"oneOf", "anyOf", "allOf"} {
		for _, branch := range schemaBranches(m[key]) {
			if item := schemaArrayItemSchema(branch); item != nil {
				return item
			}
		}
	}
	return nil
}

func schemaAllowsType(schema any, want string) bool {
	if schema == nil {
		return false
	}
	m, ok := schema.(map[string]any)
	if !ok {
		return false
	}
	switch t := m["type"].(type) {
	case string:
		if t == want {
			return true
		}
	case []any:
		for _, item := range t {
			if item == want {
				return true
			}
		}
	}
	if want == "object" && len(schemaObjectProperties(schema)) > 0 {
		return true
	}
	if want == "array" && schemaArrayItemSchema(schema) != nil {
		return true
	}
	for _, key := range []string{"oneOf", "anyOf"} {
		for _, branch := range schemaBranches(m[key]) {
			if schemaAllowsType(branch, want) {
				return true
			}
		}
	}
	if branches := schemaBranches(m["allOf"]); len(branches) > 0 {
		for _, branch := range branches {
			if schemaAllowsType(branch, want) {
				return true
			}
		}
	}
	return false
}

func schemaBranches(value any) []any {
	raw, ok := value.([]any)
	if !ok {
		return nil
	}
	return raw
}
