package wecombot

// Input and output JSON Schema builders for the WeCom Bot catalog, mirroring
// the ported OpenConnector action contracts.

const schemaDialect = "https://json-schema.org/draft/2020-12/schema"

func objectSchema(properties map[string]any, required []string) map[string]any {
	schema := map[string]any{
		"$schema":              schemaDialect,
		"type":                 "object",
		"additionalProperties": false,
		"properties":           properties,
	}
	if len(required) > 0 {
		anyRequired := make([]any, 0, len(required))
		for _, name := range required {
			anyRequired = append(anyRequired, name)
		}
		schema["required"] = anyRequired
	}
	return schema
}

func nonEmptyStringSchema(description string) map[string]any {
	return map[string]any{
		"type":        "string",
		"minLength":   1,
		"description": description,
	}
}

func stringSchema(description string) map[string]any {
	return map[string]any{"type": "string", "description": description}
}

func stringArraySchema(description string) map[string]any {
	return map[string]any{
		"type":        "array",
		"minItems":    1,
		"description": description,
		"items":       nonEmptyStringSchema("One value."),
	}
}

func newsArticleSchema() map[string]any {
	return objectSchema(map[string]any{
		"title":       nonEmptyStringSchema("The article title. Titles longer than 128 bytes are truncated by WeCom."),
		"description": stringSchema("The optional article description. Descriptions longer than 512 bytes are truncated by WeCom."),
		"url":         nonEmptyStringSchema("The URL opened after the user clicks the article."),
		"picurl":      nonEmptyStringSchema("The optional JPG or PNG image URL shown for the article."),
	}, []string{"title", "url"})
}

func sendResultSchema() map[string]any {
	return objectSchema(map[string]any{
		"errcode": map[string]any{"type": "integer", "description": "The WeCom response code. 0 means success."},
		"errmsg":  map[string]any{"type": "string", "description": "The WeCom response message."},
	}, []string{"errcode", "errmsg"})
}

func sendTextInputSchema() map[string]any {
	return objectSchema(map[string]any{
		"content":             nonEmptyStringSchema("The text content. The value can include WeCom `<@userid>` mention syntax."),
		"mentionedList":       stringArraySchema("Optional user IDs to mention explicitly."),
		"mentionedMobileList": stringArraySchema("Optional mobile numbers to mention explicitly."),
	}, []string{"content"})
}

func sendMarkdownInputSchema(variant string) map[string]any {
	description := "The markdown content encoded as UTF-8."
	if variant == "markdown_v2" {
		description = "The markdown_v2 content encoded as UTF-8. WeCom markdown_v2 does not support `@` mentions."
	}
	return objectSchema(map[string]any{
		"content": nonEmptyStringSchema(description),
	}, []string{"content"})
}

func sendImageInputSchema() map[string]any {
	return objectSchema(map[string]any{
		"base64": nonEmptyStringSchema(
			"The base64-encoded image bytes. The raw image must be a JPG or PNG no larger than 2 MB."),
		"md5": map[string]any{
			"type":        "string",
			"pattern":     "^[a-fA-F0-9]{32}$",
			"description": "The MD5 digest of the raw image bytes before base64 encoding.",
		},
	}, []string{"base64", "md5"})
}

func sendNewsInputSchema() map[string]any {
	return objectSchema(map[string]any{
		"articles": map[string]any{
			"type":        "array",
			"minItems":    1,
			"maxItems":    8,
			"description": "The news articles to send. WeCom supports 1 to 8 articles per message.",
			"items":       newsArticleSchema(),
		},
	}, []string{"articles"})
}
