import * as dntShim from "../../../_dnt.shims.js";
import { colors, Command, log, yamlParseFile } from "../../../deps.js";
import { resolveWorkspace } from "../../core/context.js";
import { requireLogin } from "../../core/auth.js";
import * as wmill from "../../../gen/services.gen.js";
import { generateAgentsDocumentation } from "../sync/sync.js";
import path from "node:path";
import * as fs from "node:fs";
/**
 * Generates DATATABLES.md content from remote workspace datatable schemas.
 * This file focuses on schema information. For full instructions, see AGENTS.md.
 */
function generateDatatablesMarkdown(schemas, localData) {
    const defaultDatatable = localData?.datatable;
    const defaultSchema = localData?.schema;
    const tables = localData?.tables ?? [];
    let content = `# Data Tables

This file contains database schema information for this app.
**For full instructions on using datatables, see \`AGENTS.md\`.**

## ⚠️ IMPORTANT

**You can ONLY use tables listed in \`data.tables\` in \`raw_app.yaml\`.**
To use a table from the schemas below, first add it to the whitelist.

## Current Configuration

${defaultDatatable
        ? `**Default Datatable:** \`${defaultDatatable}\`${defaultSchema ? ` | **Default Schema:** \`${defaultSchema}\`` : ''}`
        : `**No default datatable configured.** Set \`data.datatable\` in \`raw_app.yaml\`.`}

### Whitelisted Tables (You Can Use These)

${tables.length > 0
        ? tables.map((t) => `- \`${t}\``).join("\n")
        : `*No tables whitelisted yet.*`}

### To Add a Table

Edit \`raw_app.yaml\`:
\`\`\`yaml
data:
  datatable: ${defaultDatatable || 'main'}
  tables:
${tables.length > 0 ? tables.map((t) => `    - ${t}`).join("\n") : '    # Add tables here'}
    - ${defaultDatatable || 'main'}/${defaultSchema ? defaultSchema + ':' : ''}table_name  # ← Add like this
\`\`\`

---

## Available Schemas

`;
    if (schemas.length === 0) {
        content += `*No datatables configured in this workspace.*

Configure datatables in Workspace Settings > Windmill Data Tables.
`;
    }
    else {
        for (const dt of schemas) {
            const isDefault = dt.datatable_name === defaultDatatable;
            content += `### ${isDefault ? '★ ' : ''}Datatable: \`${dt.datatable_name}\`${isDefault ? ' (default)' : ''}

`;
            if (dt.error) {
                content += `> ⚠️ Error loading schema: ${dt.error}

`;
                continue;
            }
            if (!dt.schemas || Object.keys(dt.schemas).length === 0) {
                content += `*No schemas found.*

`;
                continue;
            }
            for (const [schemaName, schemaTables] of Object.entries(dt.schemas)) {
                const isDefaultSchema = schemaName === defaultSchema;
                content += `#### ${isDefaultSchema ? '★ ' : ''}Schema: \`${schemaName}\`${isDefaultSchema ? ' (default)' : ''}

`;
                if (!schemaTables || Object.keys(schemaTables).length === 0) {
                    content += `*No tables.*

`;
                    continue;
                }
                for (const [tableName, columns] of Object.entries(schemaTables)) {
                    const fullTableRef = schemaName === 'public'
                        ? `${dt.datatable_name}/${tableName}`
                        : `${dt.datatable_name}/${schemaName}:${tableName}`;
                    const isWhitelisted = tables.some(t => t === fullTableRef ||
                        t === `${dt.datatable_name}/${schemaName}.${tableName}` ||
                        t === dt.datatable_name);
                    content += `**\`${tableName}\`**${isWhitelisted ? ' ✓' : ''} → add as \`${fullTableRef}\`

| Column | Type |
|--------|------|
`;
                    for (const [colName, colType] of Object.entries(columns)) {
                        content += `| ${colName} | \`${colType}\` |
`;
                    }
                    content += `
`;
                }
            }
        }
    }
    content += `---
*Generated by \`wmill app generate-agents\`. See \`AGENTS.md\` for full instructions.*
`;
    return content;
}
/**
 * Regenerates AGENTS.md and DATATABLES.md for a raw app.
 * Can be called from CLI or programmatically (e.g., after SQL migration).
 */
export async function regenerateAgentDocs(workspaceId, targetDir, silent = false) {
    // Check for raw_app.yaml
    const rawAppPath = path.join(targetDir, "raw_app.yaml");
    if (!fs.existsSync(rawAppPath)) {
        if (!silent) {
            log.error(colors.red(`Error: raw_app.yaml not found in ${targetDir}`));
        }
        return;
    }
    if (!silent) {
        log.info(colors.cyan("Refreshing agent documentation..."));
    }
    // Fetch schemas
    let schemas = [];
    try {
        schemas = await wmill.listDataTableSchemas({ workspace: workspaceId });
    }
    catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (!silent) {
            log.warn(colors.yellow(`Could not fetch datatable schemas: ${errorMessage}`));
        }
    }
    // Read local data configuration from raw_app.yaml
    let localData;
    try {
        const rawApp = (await yamlParseFile(rawAppPath));
        if (rawApp.data && typeof rawApp.data === "object") {
            localData = rawApp.data;
        }
    }
    catch {
        // Ignore errors reading raw_app.yaml
    }
    // Generate and write AGENTS.md
    const agentsContent = generateAgentsDocumentation(localData);
    await dntShim.Deno.writeTextFile(path.join(targetDir, "AGENTS.md"), agentsContent);
    // Generate and write DATATABLES.md
    const datatablesContent = generateDatatablesMarkdown(schemas, localData);
    await dntShim.Deno.writeTextFile(path.join(targetDir, "DATATABLES.md"), datatablesContent);
    if (!silent) {
        log.info(colors.green(`✓ Generated AGENTS.md and DATATABLES.md`));
        // Summary
        const datatableCount = schemas.length;
        const tableCount = schemas.reduce((acc, dt) => {
            if (!dt.schemas)
                return acc;
            return (acc +
                Object.values(dt.schemas).reduce((schemaAcc, tables) => {
                    return schemaAcc + Object.keys(tables || {}).length;
                }, 0));
        }, 0);
        log.info(colors.gray(`  Found ${datatableCount} datatable(s) with ${tableCount} table(s)`));
        if (localData?.datatable) {
            log.info(colors.gray(`  App configured for datatable: ${localData.datatable}`));
        }
    }
}
async function generateAgents(opts, appFolder) {
    // Resolve the app folder
    const cwd = dntShim.Deno.cwd();
    let targetDir = cwd;
    if (appFolder) {
        targetDir = path.isAbsolute(appFolder)
            ? appFolder
            : path.join(cwd, appFolder);
    }
    // Ensure we're in a .raw_app folder or targeting one
    const dirName = path.basename(targetDir);
    if (!dirName.endsWith(".raw_app")) {
        // Check if current directory is a .raw_app folder
        if (!path.basename(cwd).endsWith(".raw_app") && !appFolder) {
            log.error(colors.red("Error: Must be run inside a .raw_app folder or specify one as argument."));
            log.info(colors.gray("Usage: wmill app generate-agents [app_folder]"));
            dntShim.Deno.exit(1);
        }
    }
    // Check for raw_app.yaml
    const rawAppPath = path.join(targetDir, "raw_app.yaml");
    if (!fs.existsSync(rawAppPath)) {
        log.error(colors.red(`Error: raw_app.yaml not found in ${targetDir}`));
        dntShim.Deno.exit(1);
    }
    // Resolve workspace and authenticate
    const workspace = await resolveWorkspace(opts);
    await requireLogin(opts);
    await regenerateAgentDocs(workspace.workspaceId, targetDir);
}
// deno-lint-ignore no-explicit-any
const command = new Command()
    .description("regenerate AGENTS.md and DATATABLES.md from remote workspace")
    .arguments("[app_folder:string]")
    .action(generateAgents);
export default command;
