"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toolRunQueryOutputSchema = exports.toolRenderChartArgsSchemaTransformed = exports.toolRenderChartArgsSchema = exports.TOOL_RENDER_CHART_DESCRIPTION = exports.parsePersistedRunQueryArgs = exports.migrateRunQueryArgsV1ToV2 = exports.isRunQueryArgsV1 = exports.toolRunQueryArgsSchemaTransformed = exports.toolRunQueryArgsSchema = exports.toolRunQueryArgsSchemaV2 = exports.toolRunQueryArgsSchemaV1 = exports.TOOL_RUN_QUERY_DESCRIPTION = void 0;
const tslib_1 = require("tslib");
const zod_1 = require("zod");
const customMetrics_1 = require("../customMetrics");
const fieldId_1 = require("../fieldId");
const filters_1 = require("../filters");
const outputMetadata_1 = require("../outputMetadata");
const sortField_1 = tslib_1.__importDefault(require("../sortField"));
const tableCalcs_1 = require("../tableCalcs/tableCalcs");
const toolSchemaBuilder_1 = require("../toolSchemaBuilder");
const visualizationMetadata_1 = tslib_1.__importDefault(require("../visualizationMetadata"));
const toolMcpQueryResultDescription_1 = require("./toolMcpQueryResultDescription");
const toolQueryResultSchemas_1 = require("./toolQueryResultSchemas");
// Query configuration schema - what data to fetch
const queryConfigBaseSchema = zod_1.z.object({
    exploreName: zod_1.z
        .string()
        .describe('The name of the explore containing the metrics and dimensions used for the chart.'),
    dimensions: zod_1.z
        .array((0, fieldId_1.getFieldIdSchema)({ additionalDescription: null }))
        .describe('The field ids for the dimensions to group the metrics by. dimensions[0] is the primary grouping (x-axis for charts). dimensions[1+] create additional grouping levels.'),
    metrics: zod_1.z
        .array((0, fieldId_1.getFieldIdSchema)({ additionalDescription: null }))
        .describe('The field ids of the metrics to be calculated. They will be grouped by the dimensions.'),
    sorts: zod_1.z
        .array(sortField_1.default)
        .describe('Sort configuration for the query, it can use a combination of metrics and dimensions.'),
    limit: zod_1.z
        .number()
        .nullable()
        .describe('The total number of data points / rows allowed on the chart.'),
});
// V1 took filters/customMetrics/tableCalculations at the top level, but LLMs
// kept nesting them (especially filters) inside queryConfig or emitting
// invalid combinations. V2 makes queryConfig the canonical (and only) place.
const queryConfigSchemaV1 = queryConfigBaseSchema.extend({
    filters: filters_1.filtersSchemaV2.nullable().default(null),
});
const queryConfigSchemaV2 = queryConfigBaseSchema.extend({
    customMetrics: customMetrics_1.customMetricsSchema,
    tableCalculations: tableCalcs_1.tableCalcsSchema,
    filters: filters_1.filtersSchemaV2.nullable(),
});
// Chart-specific configuration for rendering hints
const chartConfigSchema = zod_1.z
    .object({
    defaultVizType: zod_1.z
        .enum([
        'table',
        'bar',
        'horizontal',
        'line',
        'scatter',
        'pie',
        'funnel',
    ])
        .describe('The default visualization type to render'),
    // Axis field selection
    xAxisDimension: zod_1.z
        .string()
        .nullable()
        .describe('The dimension field ID to use for the x-axis. Must be included in queryConfig.dimensions'),
    yAxisMetrics: zod_1.z
        .array((0, fieldId_1.getFieldIdSchema)({ additionalDescription: null }))
        .nullable()
        .describe('The metric field IDs to display on the y-axis. Must be included in queryConfig.metrics or come from tableCalculations'),
    // Series creation control
    groupBy: zod_1.z
        .array((0, fieldId_1.getFieldIdSchema)({ additionalDescription: null }))
        .nullable()
        .describe('Dimensions to split metrics into separate series (e.g., one line per region, one bar per status). IMPORTANT: Do NOT include the x-axis dimension in groupBy - only include dimensions you want to use for breaking down the data into multiple series. Example: dimensions=["order_date", "status"], groupBy=["status"] creates separate series for each status value. Leave null for simple single-series charts.'),
    // Bar and horizontal bar chart specific
    xAxisType: zod_1.z
        .enum(['category', 'time'])
        .nullable()
        .describe('The x-axis type can be categorical for string value or time if the dimension is a date or timestamp. Applies to bar, horizontal, and scatter charts.'),
    stackBars: zod_1.z
        .boolean()
        .nullable()
        .describe('If groupBy is provided then this will stack the bars on top of each other instead of side by side. Applies to bar and horizontal charts.'),
    // Line chart specific
    lineType: zod_1.z
        .enum(['line', 'area'])
        .nullable()
        .describe('default line. The type of line to display. If area then the area under the line will be filled in.'),
    // Common display properties
    xAxisLabel: zod_1.z
        .string()
        .describe('A helpful label to explain the x-axis'),
    yAxisLabel: zod_1.z
        .string()
        .describe('A helpful label to explain the y-axis'),
    secondaryYAxisMetric: zod_1.z
        .string()
        .nullable()
        .describe('(Optional) A single metric field ID to display on a secondary (right) y-axis. Must NOT be included in yAxisMetrics. Use when one metric has a very different scale than others (e.g., percentage vs count).'),
    secondaryYAxisLabel: zod_1.z
        .string()
        .nullable()
        .describe('A helpful label for the secondary y-axis'),
})
    .nullable();
exports.TOOL_RUN_QUERY_DESCRIPTION = `Execute a metric query.

This tool returns metric query data only. ${(0, toolMcpQueryResultDescription_1.buildMcpVisualizationFollowUpInstruction)('run_metric_query')}

${(0, toolMcpQueryResultDescription_1.buildMcpQueryRunResponseDescription)({
    contentDescription: 'bare CSV text. CSV headers are display labels, not stable field IDs',
    completedResultShape: `    result: {
      status: "done",
      queryUuid: string,
      rows: Array<Record<string, unknown>>,
      fields: Record<string, unknown>,
      exploreUrl: string | null
    }`,
})}

Notes:
${toolMcpQueryResultDescription_1.MCP_QUERY_COMMON_NOTES}
`;
// Kept only for parsing historical persisted tool args.
exports.toolRunQueryArgsSchemaV1 = (0, toolSchemaBuilder_1.createToolSchema)()
    .extend({
    ...visualizationMetadata_1.default.shape,
    customMetrics: customMetrics_1.customMetricsSchema.default(null),
    tableCalculations: tableCalcs_1.tableCalcsSchema.default(null),
    queryConfig: queryConfigSchemaV1,
    chartConfig: chartConfigSchema.default(null),
    filters: filters_1.filtersSchemaV2.nullable().default(null),
})
    .build();
exports.toolRunQueryArgsSchemaV2 = (0, toolSchemaBuilder_1.createToolSchema)()
    .extend({
    ...visualizationMetadata_1.default.shape,
    queryConfig: queryConfigSchemaV2,
    chartConfig: chartConfigSchema,
})
    .build();
// V2 is the only schema the tools accept; this is the LLM contract and the
// canonical source of truth. V1 (below) is kept solely to parse already
// persisted tool args from old chats.
exports.toolRunQueryArgsSchema = exports.toolRunQueryArgsSchemaV2;
// Converts the raw V2 args into the internal domain shape: customMetrics and
// filters become Lightdash domain types. Piped (not transformed inline) so a
// malformed persisted value surfaces as a ZodError instead of a thrown
// exception out of safeParse.
const runQueryInternalSchema = zod_1.z.object({
    ...visualizationMetadata_1.default.shape,
    queryConfig: queryConfigBaseSchema.extend({
        customMetrics: customMetrics_1.customMetricsSchemaTransformed,
        tableCalculations: tableCalcs_1.tableCalcsSchema,
        filters: filters_1.filtersSchemaTransformed,
    }),
    chartConfig: chartConfigSchema.default(null),
});
exports.toolRunQueryArgsSchemaTransformed = exports.toolRunQueryArgsSchemaV2.pipe(runQueryInternalSchema);
// --- Backward compatibility -------------------------------------------------
// Only for parsing tool args persisted before V2. V1 put filters,
// customMetrics and tableCalculations at the top level; V2 forbids them and
// nests them inside queryConfig.
const isRunQueryArgsV1 = (args) => 'customMetrics' in args || 'tableCalculations' in args || 'filters' in args;
exports.isRunQueryArgsV1 = isRunQueryArgsV1;
const migrateRunQueryArgsV1ToV2 = (v1) => ({
    title: v1.title,
    description: v1.description,
    chartConfig: v1.chartConfig,
    queryConfig: {
        exploreName: v1.queryConfig.exploreName,
        dimensions: v1.queryConfig.dimensions,
        metrics: v1.queryConfig.metrics,
        sorts: v1.queryConfig.sorts,
        limit: v1.queryConfig.limit,
        customMetrics: v1.customMetrics,
        tableCalculations: v1.tableCalculations,
        // V1 accepted filters at the top level and (loosely) nested in
        // queryConfig; top level wins, matching the original behavior.
        filters: v1.filters ?? v1.queryConfig.filters ?? null,
    },
});
exports.migrateRunQueryArgsV1ToV2 = migrateRunQueryArgsV1ToV2;
// Single entry point for re-parsing a persisted artifact of either version.
const parsePersistedRunQueryArgs = (raw) => {
    const v2 = exports.toolRunQueryArgsSchemaTransformed.safeParse(raw);
    if (v2.success)
        return v2.data;
    const v1 = exports.toolRunQueryArgsSchemaV1.safeParse(raw);
    return v1.success
        ? exports.toolRunQueryArgsSchemaTransformed.parse((0, exports.migrateRunQueryArgsV1ToV2)(v1.data))
        : null;
};
exports.parsePersistedRunQueryArgs = parsePersistedRunQueryArgs;
exports.TOOL_RENDER_CHART_DESCRIPTION = `Render a chart for a completed query result in MCP App-capable clients.

Use this after a query tool or get_query_result returns done and the user wants a visual chart. This tool does not start, poll, or rerun the query. If the query is still running, call get_query_result first. Pass the exact queryUuid that run_metric_query (or get_query_result) returned for this query in the current conversation — it is included in that tool's response as a \`queryUuid: <id>\` text block. Never invent, guess, or reuse a queryUuid from a different query or session; an unknown id fails with "not found". Lightdash loads the completed metric query from query history.

Current support: completed run_metric_query results. SQL Runner/run_sql results are not supported by render_chart. Other query result types are rejected until their chart rendering path is implemented.

Response shape (MCP CallToolResult):
- content: [{ type: "text", text: string }] — short render status message.
- structuredContent: {
    result: {
      status: "done",
      queryUuid: string,
      exploreUrl: string | null,
      echartsOption: Record<string, unknown> | null // lightweight placeholder; full chart payload is app metadata
    }
  }`;
exports.toolRenderChartArgsSchema = (0, toolSchemaBuilder_1.createToolSchema)()
    .extend({
    queryUuid: toolQueryResultSchemas_1.mcpAsyncQueryUuidSchema.describe('Completed query UUID returned by run_metric_query (or get_query_result) in this conversation, copied from the `queryUuid: <id>` text block of that response. Do not fabricate, guess, or reuse a UUID from another query. Currently render_chart supports UUIDs from run_metric_query and does not support SQL Runner/run_sql UUIDs.'),
    chartConfig: chartConfigSchema,
    title: zod_1.z
        .string()
        .optional()
        .describe('Optional chart title used in the rendered chart.'),
    description: zod_1.z
        .string()
        .optional()
        .describe('Optional chart description used in the saved Explore URL.'),
})
    .build()
    .describe('Render chart input for a completed query.');
exports.toolRenderChartArgsSchemaTransformed = exports.toolRenderChartArgsSchema
    .extend({
    chartConfig: chartConfigSchema.default(null),
})
    .transform((data) => ({
    ...data,
    title: data.title ?? 'Metric query result',
    description: data.description ?? '',
}));
exports.toolRunQueryOutputSchema = zod_1.z.object({
    result: zod_1.z.string(),
    metadata: outputMetadata_1.baseOutputMetadataSchema.extend({
        chartImageUrl: zod_1.z.string().nullish(),
    }),
});
//# sourceMappingURL=toolRunQueryArgs.js.map