package aifin

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

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

func nonWhitespaceStringSchema(
	description string,
	maxLength int,
) map[string]any {
	return map[string]any{
		"type":        "string",
		"minLength":   1,
		"maxLength":   maxLength,
		"pattern":     "\\S",
		"description": description,
	}
}

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

func enumStringSchema(description string, values ...string) map[string]any {
	enum := make([]any, 0, len(values))
	for _, value := range values {
		enum = append(enum, value)
	}
	return map[string]any{
		"type":        "string",
		"enum":        enum,
		"description": description,
	}
}

func priceIndicatorInputSchema() map[string]any {
	return objectSchema(
		"Input for reading current price indicators for up to 50 securities.",
		map[string]any{
			"windcode": nonWhitespaceStringSchema(
				"One or more Wind security names or codes separated by commas, with at most 50 securities per call.",
				2_000,
			),
			"indexes": nonWhitespaceStringSchema(
				"Comma-separated Wind indicator names to return; omit to use Wind defaults.",
				4_000,
			),
		},
		"windcode",
	)
}

func klineInputSchema() map[string]any {
	return objectSchema(
		"Input for reading a security K-line series over an explicit date range.",
		map[string]any{
			"windcode": nonWhitespaceStringSchema(
				"The Wind security name or code.",
				200,
			),
			"begin_date": dateSchema(
				"The inclusive start date in YYYY-MM-DD format.",
			),
			"end_date": dateSchema(
				"The inclusive end date in YYYY-MM-DD format.",
			),
			"period": enumStringSchema(
				"The requested K-line aggregation period.",
				"1min", "5min", "10min", "15min", "30min", "60min",
				"120min", "240min", "1d", "1w", "1mo", "1y", "1q",
				"6mo",
			),
			"aftype": enumStringSchema(
				"The adjustment type: 0 for forward adjustment or 1 for backward adjustment.",
				"0", "1",
			),
			"issusp": enumStringSchema(
				"Whether to include suspended periods: 0 to exclude or 1 to include.",
				"0", "1",
			),
			"afdate": dateSchema(
				"The optional adjustment base date in YYYY-MM-DD format.",
			),
		},
		"windcode",
		"begin_date",
		"end_date",
	)
}

func questionInputSchema() map[string]any {
	return objectSchema(
		"Input for a natural-language Wind data query.",
		map[string]any{
			"question": nonWhitespaceStringSchema(
				"A natural-language request containing the relevant entity, indicators, and date or reporting period when applicable.",
				4_000,
			),
		},
		"question",
	)
}

func documentSearchInputSchema() map[string]any {
	return objectSchema(
		"Input for searching Wind financial documents.",
		map[string]any{
			"query": nonWhitespaceStringSchema(
				"A natural-language search query containing the topic or entity and date range when applicable.",
				4_000,
			),
			"top_k": map[string]any{
				"type":        "integer",
				"minimum":     1,
				"maximum":     100,
				"description": "The maximum number of relevant documents or excerpts to return; defaults to 5.",
			},
		},
		"query",
	)
}

func economicDataInputSchema() map[string]any {
	return objectSchema(
		"Input for searching or fetching Wind EDB economic indicators.",
		map[string]any{
			"executionMode": enumStringSchema(
				"Whether to search indicators, fetch values, or do both.",
				"search", "fetch", "searchFetch", "仅搜索", "仅提数",
				"搜索并提数",
			),
			"question": nonWhitespaceStringSchema(
				"A natural-language indicator query for search modes, or comma-separated EDB indicator codes for fetch mode.",
				4_000,
			),
			"beginDate": dateSchema(
				"The inclusive data start date in YYYY-MM-DD format.",
			),
			"endDate": dateSchema(
				"The inclusive data end date in YYYY-MM-DD format.",
			),
			"observation": map[string]any{
				"type":        "string",
				"minLength":   1,
				"maxLength":   6,
				"pattern":     "^(all|[0-9]+)$",
				"description": "A number of recent observations, or all for the complete series.",
			},
		},
		"executionMode",
		"question",
	)
}

func toolResultOutputSchema() map[string]any {
	return objectSchema(
		"The normalized result returned by the Wind MCP tool.",
		map[string]any{
			"result": map[string]any{
				"description": "The JSON value returned by the named Wind MCP tool.",
			},
		},
		"result",
	)
}
