// tools/design-schema.ts — Data-first schema design
// Analyzes a spec to generate database schema recommendations including
// tables, indexes, RLS policies, migrations, and relationships.
import { readFile } from 'node:fs/promises';
import { specStore, knowledgeStore } from '../storage/index.js';
import { t, ti } from '../i18n/index.js';
import { isMobileSchema, generateMobileSchema } from './design-schema-mobile.js';
import { isGameSchema, generateGameSchema } from './design-schema-games.js';
import { extractEntities, injectPrivacyAuditFields, isMcpSchema, generateMcpSchema, isSmartContractSchema, isMLSchema, isDbtSchema, generateSmartContractSchema, generateMLSchema, generateDbtSchema, isCacheSchema, generateCacheSchema, isSearchSchema, generateSearchSchema, isTimeseriesSchema, generateTimeseriesSchema, isVectorSchema, generateVectorSchema, isGraphSchema, generateGraphSchema, isWideColumnSchema, generateWideColumnSchema, isCloudManagedSchema, generateCloudManagedSchema, } from './design-schema/index.js';
import { generateTables, generateIndexes, generateRLSPolicies, generateMigrations, buildRelationships, buildDataIntegrityRules, } from './design-schema-sql.js';
import { detectPIIInSpec } from '../engine/pii-detector.js';
export async function handleDesignSchema(args) {
    const { specId, projectId, description } = args;
    const spec = await specStore.getSpec(projectId, specId);
    if (!spec) {
        return {
            content: [{ type: 'text', text: ti('spec.notFound', { id: specId }) }],
            isError: true,
        };
    }
    const knowledge = await knowledgeStore.getKnowledge(projectId);
    if (!knowledge) {
        return {
            content: [{ type: 'text', text: t('project.notFound') }],
            isError: true,
        };
    }
    const specContent = await readSpecContent(spec, description);
    const entities = extractEntities(specContent);
    const dbEngine = knowledge.database;
    // SPEC-043: Server-side rendering projects don't use SPA schema patterns
    const rendering = knowledge.rendering;
    if (rendering === 'server-side') {
        return {
            content: [
                {
                    type: 'text',
                    text: [
                        '## Schema Design \u2014 Backend-First Project',
                        '',
                        '**Rendering mode:** Server-Side \u2014 SPA schema patterns excluded.',
                        '',
                        'For hypermedia/backend-first projects, schema design follows server-side conventions:',
                        '- No client-side state schemas (Redux/Zustand/Pinia stores)',
                        '- No GraphQL client cache schemas',
                        '- Data models are defined server-side (ORM models, database tables)',
                        '',
                        'Use `design_schema` for database table design if your project uses a relational DB.',
                        'The following entities were detected from the spec:',
                        ...entities.map((e) => `- **${e.name}** (fields: ${e.fields.join(', ')})`),
                    ].join('\n'),
                },
            ],
        };
    }
    // SPEC-016b: MCP server schema (TypeScript interfaces per tool)
    if (isMcpSchema(knowledge)) {
        return {
            content: [
                {
                    type: 'text',
                    text: ti('tools.design_schema.success', {
                        tableCount: String(entities.length),
                        indexCount: '0',
                    }),
                },
                {
                    type: 'text',
                    text: generateMcpSchema(entities.map((e) => e.name), knowledge),
                },
            ],
        };
    }
    if (isMobileSchema(knowledge)) {
        return {
            content: [
                {
                    type: 'text',
                    text: ti('tools.design_schema.success', {
                        tableCount: String(entities.length),
                        indexCount: '0',
                    }),
                },
                { type: 'text', text: generateMobileSchema(entities, knowledge) },
            ],
        };
    }
    if (isGameSchema(knowledge)) {
        return {
            content: [
                {
                    type: 'text',
                    text: ti('tools.design_schema.success', {
                        tableCount: String(entities.length),
                        indexCount: '0',
                    }),
                },
                {
                    type: 'text',
                    text: generateGameSchema(entities.map((e) => e.name), knowledge),
                },
            ],
        };
    }
    // SPEC-015a: Smart contract schema (criterion 7)
    if (isSmartContractSchema(knowledge)) {
        return {
            content: [
                {
                    type: 'text',
                    text: ti('tools.design_schema.success', {
                        tableCount: String(entities.length),
                        indexCount: '0',
                    }),
                },
                {
                    type: 'text',
                    text: generateSmartContractSchema(entities.map((e) => e.name), knowledge),
                },
            ],
        };
    }
    // SPEC-015b: dbt schema
    if (isDbtSchema(knowledge)) {
        return {
            content: [
                {
                    type: 'text',
                    text: ti('tools.design_schema.success', {
                        tableCount: String(entities.length),
                        indexCount: '0',
                    }),
                },
                {
                    type: 'text',
                    text: generateDbtSchema(entities.map((e) => e.name), knowledge),
                },
            ],
        };
    }
    // SPEC-015a: ML schema (criterion 8)
    if (isMLSchema(knowledge)) {
        return {
            content: [
                {
                    type: 'text',
                    text: ti('tools.design_schema.success', {
                        tableCount: String(entities.length),
                        indexCount: '0',
                    }),
                },
                {
                    type: 'text',
                    text: generateMLSchema(entities.map((e) => e.name), knowledge),
                },
            ],
        };
    }
    // SPEC-059: Specialized DB category schemas
    const specializedResult = trySpecializedDbSchema(entities, knowledge);
    if (specializedResult) {
        return specializedResult;
    }
    const tables = generateTables(entities, dbEngine);
    // SPEC-030: Inject privacy audit fields for entities with PII context
    const piiResult = detectPIIInSpec(spec.title, specContent, specContent);
    if (piiResult.hasPII) {
        injectPrivacyAuditFields(tables, dbEngine);
    }
    const indexes = generateIndexes(tables, dbEngine);
    const rlsPolicies = dbEngine === 'supabase' || dbEngine === 'postgresql' ? generateRLSPolicies(tables) : [];
    const migrations = generateMigrations(tables, indexes, rlsPolicies, dbEngine);
    const relationships = buildRelationships(tables);
    const dataIntegrity = buildDataIntegrityRules(tables, dbEngine);
    const schema = {
        engine: dbEngine,
        tables,
        indexes,
        rlsPolicies,
        migrations,
        relationships,
        dataIntegrity,
    };
    return {
        content: [
            {
                type: 'text',
                text: ti('tools.design_schema.success', {
                    tableCount: String(tables.length),
                    indexCount: String(indexes.length),
                }),
            },
            {
                type: 'text',
                text: JSON.stringify(schema, null, 2),
            },
        ],
    };
}
// -- SPEC-059: Specialized DB schema dispatch ---------------------------------
const SPECIALIZED_DB_CHECKS = [
    { detect: isCacheSchema, generate: generateCacheSchema },
    { detect: isSearchSchema, generate: generateSearchSchema },
    { detect: isTimeseriesSchema, generate: generateTimeseriesSchema },
    { detect: isVectorSchema, generate: generateVectorSchema },
    { detect: isGraphSchema, generate: generateGraphSchema },
    { detect: isWideColumnSchema, generate: generateWideColumnSchema },
    { detect: isCloudManagedSchema, generate: generateCloudManagedSchema },
];
function trySpecializedDbSchema(entities, knowledge) {
    for (const check of SPECIALIZED_DB_CHECKS) {
        /* v8 ignore next 1 -- specialized DB schemas tested in nosql-category-schemas.test.ts + advanced-db-schemas.test.ts */
        if (check.detect(knowledge)) {
            /* v8 ignore start */
            return {
                content: [
                    {
                        type: 'text',
                        text: ti('tools.design_schema.success', {
                            tableCount: String(entities.length),
                            indexCount: '0',
                        }),
                    },
                    {
                        type: 'text',
                        text: check.generate(entities.map((e) => e.name), knowledge),
                    },
                ],
            };
            /* v8 ignore stop */
        }
    }
    return null;
}
// -- I/O helpers --------------------------------------------------------------
async function readSpecContent(spec, additionalDescription) {
    let content = `${spec.title} ${spec.type} ${spec.scope} ${spec.target}`;
    if (additionalDescription) {
        content += ' ' + additionalDescription;
    }
    try {
        if (spec.specPath) {
            content += ' ' + (await readFile(spec.specPath, 'utf-8'));
        }
    }
    catch {
        /* file not available */
    }
    try {
        if (spec.technicalPath) {
            content += ' ' + (await readFile(spec.technicalPath, 'utf-8'));
        }
    }
    catch {
        /* file not available */
    }
    return content;
}
//# sourceMappingURL=design-schema.js.map