"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildDefaultModuleContractPath = buildDefaultModuleContractPath;
exports.buildDefaultModulePublicEntrypoints = buildDefaultModulePublicEntrypoints;
exports.loadArchitectureContract = loadArchitectureContract;
exports.saveArchitectureContract = saveArchitectureContract;
exports.writeArchitectureConfig = writeArchitectureConfig;
exports.generateDocs = generateDocs;
exports.generateContracts = generateContracts;
exports.generateDatabaseFiles = generateDatabaseFiles;
exports.generateArchpilotConfigFiles = generateArchpilotConfigFiles;
exports.ensureArchpilotIgnoreFile = ensureArchpilotIgnoreFile;
exports.applyArchitectureInitialization = applyArchitectureInitialization;
const path = __importStar(require("node:path"));
const node_fs_1 = require("node:fs");
const adrTemplate_1 = require("./adr/adrTemplate");
const setupNextSteps_1 = require("./setupNextSteps");
const architectureMap_1 = require("./architectureMap");
const architectureMapReporter_1 = require("./reporting/architectureMapReporter");
const managedArtifacts_1 = require("./managedArtifacts");
const riskPolicyInitializer_1 = require("./policy/riskPolicyInitializer");
const archpilotIgnore_1 = require("./smartInit/archpilotIgnore");
const moduleDiscovery_1 = require("./moduleDiscovery");
const stackMetadata_1 = require("./stackMetadata");
const stackAdapters_1 = require("./stackAdapters");
function hasConfiguredApi(config) {
    return config.apiStyle !== 'none';
}
function hasConfiguredDatabase(config) {
    return config.database !== 'none';
}
function nowUtcIso() {
    return new Date().toISOString();
}
async function ensureDir(dirPath) {
    await node_fs_1.promises.mkdir(dirPath, { recursive: true });
}
async function fileExists(filePath) {
    try {
        await node_fs_1.promises.access(filePath);
        return true;
    }
    catch {
        return false;
    }
}
async function writeFileIfMissing(filePath, contents) {
    if (await fileExists(filePath)) {
        return false;
    }
    await ensureDir(path.dirname(filePath));
    await node_fs_1.promises.writeFile(filePath, contents, { encoding: 'utf8' });
    return true;
}
function labelTenantModel(model) {
    switch (model) {
        case 'single_tenant':
            return 'Single tenant (one tenant per deployment)';
        case 'same_db_same_schema':
            return 'Multi-tenant: same DB, same schema (tenant_id discriminator)';
        case 'same_db_different_schema':
            return 'Multi-tenant: same DB, different schema per tenant';
    }
}
function defaultArchitectureContractSections(config) {
    const apiEnabled = config?.apiStyle !== 'none';
    const databaseEnabled = config?.database !== 'none';
    const adapter = (0, stackAdapters_1.resolvePrimaryAdapterFromContract)(config);
    const modulesRoot = adapter.scaffoldingDefaults?.modulesRoot ?? 'src/modules';
    return {
        structure: {
            modulesRoot,
            docsRoot: 'docs',
            ...(apiEnabled ? { apiRoot: 'contracts' } : {}),
            ...(databaseEnabled ? { databaseRoot: 'db/sql' } : {}),
            contractsRoot: '.archpilot/contracts',
        },
        artifacts: {
            architectureOverview: 'docs/architecture/overview.md',
            adrDirectory: 'docs/adrs',
            ...(apiEnabled ? { openApiSpec: 'contracts/openapi.yaml' } : {}),
            ...(databaseEnabled ? { sqlBaseline: 'db/sql/001_init.sql' } : {}),
        },
        modules: {},
        layers: {},
        governance: {
            validation: {
                enforceModuleBoundaries: false,
                enforceLayerRules: false,
                highInboundDependencyWarningThreshold: 3,
            },
        },
    };
}
function normalizeArchitectureModuleContractReference(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return undefined;
    }
    const typedValue = value;
    const pathValue = typeof typedValue.path === 'string' ? typedValue.path : undefined;
    const contractValue = typeof typedValue.contract === 'string' ? typedValue.contract : undefined;
    const publicEntrypointsValue = Array.isArray(typedValue.publicEntrypoints)
        ? typedValue.publicEntrypoints.filter((entry) => typeof entry === 'string')
        : undefined;
    return {
        ...(pathValue ? { path: pathValue } : {}),
        ...(contractValue ? { contract: contractValue } : {}),
        ...(publicEntrypointsValue ? { publicEntrypoints: publicEntrypointsValue } : {}),
    };
}
function normalizeArchitectureModuleRegistry(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return {};
    }
    return Object.entries(value)
        .sort(([left], [right]) => left.localeCompare(right))
        .reduce((accumulator, [moduleName, moduleValue]) => {
        const normalizedReference = normalizeArchitectureModuleContractReference(moduleValue);
        if (normalizedReference) {
            accumulator[moduleName] = normalizedReference;
        }
        return accumulator;
    }, {});
}
function normalizeOptionalStringRecord(value) {
    return value && typeof value === 'object' && !Array.isArray(value)
        ? { ...value }
        : undefined;
}
function normalizeOptionalStringArray(value) {
    if (!Array.isArray(value)) {
        return undefined;
    }
    const normalized = value.filter((entry) => typeof entry === 'string');
    return normalized.length > 0 ? normalized : undefined;
}
function normalizeOptionalString(value) {
    return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
}
function normalizeArchitectureStructure(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return undefined;
    }
    const typedValue = value;
    const modulesRoot = typeof typedValue.modulesRoot === 'string' ? typedValue.modulesRoot : undefined;
    const docsRoot = typeof typedValue.docsRoot === 'string' ? typedValue.docsRoot : undefined;
    const apiRoot = typeof typedValue.apiRoot === 'string' ? typedValue.apiRoot : undefined;
    const databaseRoot = typeof typedValue.databaseRoot === 'string' ? typedValue.databaseRoot : undefined;
    const contractsRoot = typeof typedValue.contractsRoot === 'string'
        ? typedValue.contractsRoot
        : undefined;
    return {
        ...(modulesRoot ? { modulesRoot } : {}),
        ...(docsRoot ? { docsRoot } : {}),
        ...(apiRoot ? { apiRoot } : {}),
        ...(databaseRoot ? { databaseRoot } : {}),
        ...(contractsRoot ? { contractsRoot } : {}),
    };
}
function normalizeArchitectureArtifacts(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return undefined;
    }
    const typedValue = value;
    const architectureOverview = typeof typedValue.architectureOverview === 'string'
        ? typedValue.architectureOverview
        : undefined;
    const adrDirectory = typeof typedValue.adrDirectory === 'string' ? typedValue.adrDirectory : undefined;
    const openApiSpec = typeof typedValue.openApiSpec === 'string' ? typedValue.openApiSpec : undefined;
    const sqlBaseline = typeof typedValue.sqlBaseline === 'string' ? typedValue.sqlBaseline : undefined;
    return {
        ...(architectureOverview ? { architectureOverview } : {}),
        ...(adrDirectory ? { adrDirectory } : {}),
        ...(openApiSpec ? { openApiSpec } : {}),
        ...(sqlBaseline ? { sqlBaseline } : {}),
    };
}
function normalizeArchitectureGovernance(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return undefined;
    }
    const typedValue = value;
    const validation = typedValue.validation &&
        typeof typedValue.validation === 'object' &&
        !Array.isArray(typedValue.validation)
        ? typedValue.validation
        : undefined;
    return {
        ...(validation
            ? {
                validation: {
                    ...(typeof validation.enforceModuleBoundaries === 'boolean'
                        ? {
                            enforceModuleBoundaries: validation.enforceModuleBoundaries,
                        }
                        : {}),
                    ...(typeof validation.enforceLayerRules === 'boolean'
                        ? { enforceLayerRules: validation.enforceLayerRules }
                        : {}),
                    ...(typeof validation.highInboundDependencyWarningThreshold ===
                        'number'
                        ? {
                            highInboundDependencyWarningThreshold: validation.highInboundDependencyWarningThreshold,
                        }
                        : {}),
                },
            }
            : {}),
    };
}
function normalizeArchitectureStyle(value) {
    return value === 'modular_monolith' || value === 'multi_component_monorepo' || value === 'microservices'
        ? value
        : undefined;
}
function normalizeDatabaseChoice(value) {
    return value === 'none' || value === 'postgresql' || value === 'mysql'
        ? value
        : undefined;
}
function normalizeTenantModel(value) {
    return value === 'single_tenant' ||
        value === 'same_db_same_schema' ||
        value === 'same_db_different_schema'
        ? value
        : undefined;
}
function normalizeApiStyle(value) {
    return value === 'none' || value === 'rest' || value === 'graphql'
        ? value
        : undefined;
}
function normalizeAuthStyle(value) {
    return value === 'jwt' || value === 'session' ? value : undefined;
}
function normalizeArchitectureComponentConfig(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return undefined;
    }
    const typedValue = value;
    const stackMetadata = (0, stackMetadata_1.normalizeStackMetadata)(typedValue);
    const projectKinds = Array.isArray(typedValue.projectKinds)
        ? stackMetadata.projectKinds
        : undefined;
    const stacks = typedValue.stacks && Object.keys(stackMetadata.stacks).length > 0
        ? stackMetadata.stacks
        : undefined;
    const modules = typedValue.modules !== undefined
        ? normalizeArchitectureModuleRegistry(typedValue.modules)
        : undefined;
    const layers = normalizeOptionalStringRecord(typedValue.layers);
    const structure = normalizeArchitectureStructure(typedValue.structure);
    const artifacts = normalizeArchitectureArtifacts(typedValue.artifacts);
    const governance = normalizeArchitectureGovernance(typedValue.governance);
    const id = normalizeOptionalString(typedValue.id);
    const componentPath = normalizeOptionalString(typedValue.path);
    const componentType = normalizeOptionalString(typedValue.type);
    const stack = normalizeOptionalString(typedValue.stack);
    const kind = normalizeOptionalString(typedValue.kind);
    const allowedDependencies = Array.isArray(typedValue.allowedDependencies)
        ? [...new Set(typedValue.allowedDependencies.filter((entry) => typeof entry === 'string' && entry.trim().length > 0).map((entry) => entry.trim()))].sort((left, right) => left.localeCompare(right))
        : undefined;
    return {
        ...(id ? { id } : {}),
        ...(typeof typedValue.name === 'string' ? { name: typedValue.name } : {}),
        ...(componentPath ? { path: componentPath } : {}),
        ...(componentType ? { type: componentType } : {}),
        ...(stack ? { stack: stack } : {}),
        ...(kind ? { kind: kind } : {}),
        ...(typedValue.repoTopology ? { repoTopology: stackMetadata.repoTopology } : {}),
        ...(projectKinds ? { projectKinds } : {}),
        ...(stacks ? { stacks } : {}),
        ...(normalizeArchitectureStyle(typedValue.architectureStyle)
            ? { architectureStyle: normalizeArchitectureStyle(typedValue.architectureStyle) }
            : {}),
        ...(normalizeDatabaseChoice(typedValue.database)
            ? { database: normalizeDatabaseChoice(typedValue.database) }
            : {}),
        ...(normalizeTenantModel(typedValue.tenantModel)
            ? { tenantModel: normalizeTenantModel(typedValue.tenantModel) }
            : {}),
        ...(typeof typedValue.rbac === 'boolean' ? { rbac: typedValue.rbac } : {}),
        ...(normalizeApiStyle(typedValue.apiStyle)
            ? { apiStyle: normalizeApiStyle(typedValue.apiStyle) }
            : {}),
        ...(normalizeAuthStyle(typedValue.authStyle)
            ? { authStyle: normalizeAuthStyle(typedValue.authStyle) }
            : {}),
        ...(typeof typedValue.implementationProfile === 'string'
            ? {
                implementationProfile: typedValue.implementationProfile,
            }
            : {}),
        ...(structure ? { structure } : {}),
        ...(artifacts ? { artifacts } : {}),
        ...(modules ? { modules } : {}),
        ...(Array.isArray(typedValue.allowedDependencies)
            ? { allowedDependencies: allowedDependencies ?? [] }
            : {}),
        ...(layers ? { layers } : {}),
        ...(governance ? { governance } : {}),
    };
}
function normalizeArchitectureComponents(value) {
    if (!value || typeof value !== 'object') {
        return undefined;
    }
    const entries = Array.isArray(value)
        ? value.map((componentValue, index) => [`component-${index + 1}`, componentValue])
        : Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
    const components = entries.reduce((accumulator, [fallbackComponentId, componentValue]) => {
        const normalizedComponent = normalizeArchitectureComponentConfig(componentValue);
        if (normalizedComponent) {
            const componentId = normalizedComponent.id ?? fallbackComponentId;
            accumulator[componentId] = normalizedComponent;
        }
        return accumulator;
    }, {});
    return Object.keys(components).length > 0 ? components : undefined;
}
function normalizeArchitectureResourceConfig(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return undefined;
    }
    const typedValue = value;
    const components = normalizeOptionalStringArray(typedValue.components);
    const dependsOn = normalizeOptionalStringArray(typedValue.dependsOn);
    const metadata = normalizeOptionalStringRecord(typedValue.metadata);
    const id = normalizeOptionalString(typedValue.id);
    return {
        ...(id ? { id } : {}),
        ...(typeof typedValue.name === 'string' ? { name: typedValue.name } : {}),
        ...(typeof typedValue.type === 'string' ? { type: typedValue.type } : {}),
        ...(typeof typedValue.provider === 'string'
            ? { provider: typedValue.provider }
            : {}),
        ...(typeof typedValue.path === 'string' ? { path: typedValue.path } : {}),
        ...(typeof typedValue.ownerComponent === 'string'
            ? { ownerComponent: typedValue.ownerComponent }
            : {}),
        ...(typeof typedValue.component === 'string'
            ? { component: typedValue.component }
            : {}),
        ...(components ? { components } : {}),
        ...(dependsOn ? { dependsOn } : {}),
        ...(metadata ? { metadata } : {}),
    };
}
function normalizeArchitectureResources(value) {
    if (!value || typeof value !== 'object') {
        return undefined;
    }
    const entries = Array.isArray(value)
        ? value.map((resourceValue, index) => [`resource-${index + 1}`, resourceValue])
        : Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
    const resources = entries.reduce((accumulator, [fallbackResourceId, resourceValue]) => {
        const normalizedResource = normalizeArchitectureResourceConfig(resourceValue);
        if (normalizedResource) {
            const resourceId = normalizedResource.id ?? fallbackResourceId;
            accumulator[resourceId] = normalizedResource;
        }
        return accumulator;
    }, {});
    return Object.keys(resources).length > 0 ? resources : undefined;
}
function buildArchitectureContract(base, overrides) {
    const defaults = defaultArchitectureContractSections(base);
    const contract = {
        version: base.version,
        projectName: base.projectName,
        repoTopology: base.repoTopology,
        projectKinds: [...base.projectKinds],
        stacks: { ...base.stacks },
        architectureStyle: base.architectureStyle,
        database: base.database,
        tenantModel: base.tenantModel,
        rbac: typeof overrides?.rbac === 'boolean' ? overrides.rbac : base.rbac,
        apiStyle: base.apiStyle,
        authStyle: base.authStyle,
        implementationProfile: (typeof overrides?.implementationProfile === 'string' &&
            overrides.implementationProfile) ||
            base.implementationProfile,
        createdAtUtc: typeof overrides?.createdAtUtc === 'string'
            ? overrides.createdAtUtc
            : base.createdAtUtc,
        structure: {
            ...defaults.structure,
            ...(overrides?.structure ?? {}),
        },
        artifacts: {
            ...defaults.artifacts,
            ...(overrides?.artifacts ?? {}),
        },
        modules: overrides?.modules !== undefined
            ? normalizeArchitectureModuleRegistry(overrides.modules)
            : defaults.modules,
        layers: overrides?.layers &&
            typeof overrides.layers === 'object' &&
            !Array.isArray(overrides.layers)
            ? { ...overrides.layers }
            : defaults.layers,
        governance: {
            ...defaults.governance,
            ...(overrides?.governance ?? {}),
            validation: {
                ...defaults.governance.validation,
                ...(overrides?.governance?.validation ?? {}),
            },
        },
    };
    if (!hasConfiguredApi(base)) {
        delete contract.structure.apiRoot;
        delete contract.artifacts.openApiSpec;
    }
    if (!hasConfiguredDatabase(base)) {
        delete contract.structure.databaseRoot;
        delete contract.artifacts.sqlBaseline;
    }
    return contract;
}
function buildDefaultModuleContractPath(moduleName, contract) {
    const contractsRoot = (0, moduleDiscovery_1.resolveContractsRootFromContract)(contract);
    const safeModuleName = moduleName
        .replace(/\\/g, '/')
        .split('/')
        .map((segment) => segment.trim())
        .filter((segment) => segment.length > 0)
        .join('.');
    return `${contractsRoot}/${safeModuleName}.contract.json`;
}
function buildDefaultModulePublicEntrypoints(moduleName, contract) {
    const modulesRoot = (0, moduleDiscovery_1.resolveModulesRootFromContract)(contract);
    const adapter = (0, stackAdapters_1.resolvePrimaryAdapterFromContract)(contract);
    const moduleIndexFileName = adapter.scaffoldingDefaults?.moduleIndexFileName ?? 'index.ts';
    const entrypoints = [`${modulesRoot}/${moduleName}/${moduleIndexFileName}`];
    const publicDirectoryName = adapter.publicEntrypointDirectoryNames[0];
    if (publicDirectoryName && publicDirectoryName.trim().length > 0) {
        entrypoints.push(`${modulesRoot}/${moduleName}/${publicDirectoryName}`);
    }
    return entrypoints;
}
function overviewTemplate(config) {
    const stackSummary = [
        config.stacks.backendStack ? `backend=${config.stacks.backendStack}` : undefined,
        config.stacks.frontendStack ? `frontend=${config.stacks.frontendStack}` : undefined,
        config.stacks.libraryStack ? `library=${config.stacks.libraryStack}` : undefined,
    ]
        .filter((entry) => typeof entry === 'string')
        .join(', ');
    return `# Architecture Overview

## Summary
- **Project**: ${config.projectName}
- **Repository topology**: ${config.repoTopology}
- **Project kinds**: ${config.projectKinds.join(', ')}
- **Stacks**: ${stackSummary.length > 0 ? stackSummary : 'not specified'}
- **Architecture style**: ${config.architectureStyle}
- **API style**: ${config.apiStyle}
- **Auth style**: ${config.authStyle}
- **Database**: ${config.database}
- **Tenant model**: ${config.tenantModel} - ${labelTenantModel(config.tenantModel)}

## Implementation notes
- This repository was initialized by **ArchPilot** in offline mode.
- Edit \`.archpilot/architecture.json\` to reflect future decisions.

## Next steps
- Add service/module boundaries (packages or folders) consistent with **${config.architectureStyle}**.
- Expand the API contract in \`contracts/openapi.yaml\`.
- Add additional ADRs as decisions are made.
`;
}
function adrTenantModelTemplate(config) {
    const decision = labelTenantModel(config.tenantModel);
    const schemaNotes = config.tenantModel === 'same_db_different_schema'
        ? '- Each tenant maps to a dedicated schema.\n- Cross-tenant access is prevented via schema isolation.'
        : config.tenantModel === 'same_db_same_schema'
            ? '- Shared schema with a required `tenant_id` discriminator on tenant-scoped tables.\n- Access control must filter by `tenant_id` at all data access boundaries.'
            : '- Tenant isolation is achieved by separate deployments/environments.\n- Data separation is handled operationally rather than in-schema.';
    return `# ADR-001: Tenant model

Status: Accepted

## Context
${config.projectName} needs a tenant strategy that matches the product and operational model.

Chosen inputs:
- **Tenant model**: ${config.tenantModel}
- **Database**: ${config.database}
- **Architecture style**: ${config.architectureStyle}

## Decision
We will use: **${decision}**.

## Consequences
${schemaNotes}

- We will document tenant boundaries in endpoints, data model, and operational runbooks.
- We will revisit this decision if scaling, compliance, or customer isolation requirements change.

## Alternatives Considered
Optional.

## Migration Plan
Optional.

## References
Optional.
`;
}
function openApiTemplate(config) {
    const paths = config.apiStyle === 'graphql'
        ? `  /graphql:
    post:
      summary: GraphQL endpoint
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
      responses:
        '200':
          description: OK
`
        : `  /health:
    get:
      summary: Health check
      responses:
        '200':
          description: OK
`;
    const securitySchemes = config.authStyle === 'jwt'
        ? `    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
`
        : `    cookieAuth:
      type: apiKey
      in: cookie
      name: session
`;
    return `openapi: 3.0.3
info:
  title: ${config.projectName} API
  version: 0.1.0
servers:
  - url: http://localhost:3000
paths:
${paths}components:
  securitySchemes:
${securitySchemes}`;
}
function sqlTemplate(config) {
    const tenantColumnsSameSchema = config.tenantModel === 'same_db_same_schema'
        ? config.database === 'postgresql'
            ? `  tenant_id UUID NOT NULL,\n`
            : `  tenant_id CHAR(36) NOT NULL,\n`
        : '';
    const idColumn = config.database === 'postgresql'
        ? `id UUID PRIMARY KEY`
        : `id CHAR(36) PRIMARY KEY`;
    const createdAtColumn = config.database === 'postgresql'
        ? `created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()`
        : `created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP`;
    if (config.database === 'postgresql') {
        return `-- ArchPilot initialization SQL (PostgreSQL)

CREATE TABLE IF NOT EXISTS app_user (
  ${idColumn},
${tenantColumnsSameSchema}  email TEXT NOT NULL UNIQUE,
  ${createdAtColumn}
);
`;
    }
    return `-- ArchPilot initialization SQL (MySQL)

CREATE TABLE IF NOT EXISTS app_user (
  ${idColumn},
${tenantColumnsSameSchema}  email VARCHAR(320) NOT NULL UNIQUE,
  ${createdAtColumn}
);
`;
}
const defaultLayerRulesTemplate = `{
  "layers": ["api", "service", "domain", "infrastructure"],
  "moduleLayers": {}
}
`;
const defaultDependencyRulesTemplate = `{
  "modules": {}
}
`;
async function loadArchitectureContract(workspaceRoot) {
    const configPath = path.join(workspaceRoot, '.archpilot', 'architecture.json');
    const contents = await node_fs_1.promises.readFile(configPath, { encoding: 'utf8' }).catch(() => undefined);
    if (!contents) {
        return undefined;
    }
    let parsed;
    try {
        parsed = JSON.parse(contents);
    }
    catch {
        throw new Error('ArchPilot configuration is invalid JSON. Please fix .archpilot/architecture.json.');
    }
    const baseConfig = {
        version: 1,
        projectName: typeof parsed.projectName === 'string' ? parsed.projectName : '',
        ...(0, stackMetadata_1.normalizeStackMetadata)(parsed),
        architectureStyle: parsed.architectureStyle === 'modular_monolith' ||
            parsed.architectureStyle === 'multi_component_monorepo' ||
            parsed.architectureStyle === 'microservices'
            ? parsed.architectureStyle
            : 'modular_monolith',
        database: parsed.database === 'none' ||
            parsed.database === 'postgresql' ||
            parsed.database === 'mysql'
            ? parsed.database
            : 'postgresql',
        tenantModel: parsed.tenantModel === 'single_tenant' ||
            parsed.tenantModel === 'same_db_same_schema' ||
            parsed.tenantModel === 'same_db_different_schema'
            ? parsed.tenantModel
            : 'single_tenant',
        rbac: typeof parsed.rbac === 'boolean' ? parsed.rbac : false,
        apiStyle: parsed.apiStyle === 'none' ||
            parsed.apiStyle === 'rest' ||
            parsed.apiStyle === 'graphql'
            ? parsed.apiStyle
            : 'rest',
        authStyle: parsed.authStyle === 'jwt' || parsed.authStyle === 'session'
            ? parsed.authStyle
            : 'jwt',
        implementationProfile: (typeof parsed.implementationProfile === 'string' &&
            parsed.implementationProfile) ||
            'typescript-backend',
        createdAtUtc: typeof parsed.createdAtUtc === 'string' ? parsed.createdAtUtc : nowUtcIso(),
    };
    const contract = buildArchitectureContract(baseConfig, parsed);
    contract.structure.modulesRoot = (0, moduleDiscovery_1.resolveModulesRootFromContract)(parsed, contract.structure.modulesRoot);
    const components = normalizeArchitectureComponents(parsed.components);
    if (components) {
        contract.components = components;
    }
    const resources = normalizeArchitectureResources(parsed.resources);
    if (resources) {
        contract.resources = resources;
    }
    return contract;
}
async function saveArchitectureContract(workspaceRoot, contract) {
    const configDir = path.join(workspaceRoot, '.archpilot');
    const configPath = path.join(configDir, 'architecture.json');
    await ensureDir(configDir);
    await node_fs_1.promises.writeFile(configPath, `${JSON.stringify(contract, null, 2)}\n`, {
        encoding: 'utf8',
    });
}
async function writeArchitectureConfig(workspaceRoot, inputs) {
    const baseConfig = {
        version: 1,
        ...inputs,
        rbac: false,
        createdAtUtc: nowUtcIso(),
    };
    const configDir = path.join(workspaceRoot, '.archpilot');
    const configPath = path.join(configDir, 'architecture.json');
    await ensureDir(configDir);
    let config = buildArchitectureContract(baseConfig);
    const existingContract = await loadArchitectureContract(workspaceRoot);
    if (existingContract) {
        config = buildArchitectureContract(baseConfig, existingContract);
    }
    const normalizedModulesRoot = typeof inputs.modulesRoot === 'string' ? inputs.modulesRoot.trim() : '';
    if (normalizedModulesRoot.length > 0) {
        config.structure.modulesRoot = normalizedModulesRoot;
    }
    const normalizedModules = Array.isArray(inputs.modules)
        ? inputs.modules
            .map((entry) => (typeof entry === 'string' ? entry.trim() : ''))
            .filter((entry) => entry.length > 0)
            .filter((entry, index, array) => array.indexOf(entry) === index)
        : [];
    if (Array.isArray(inputs.modules)) {
        const moduleRegistry = {};
        for (const moduleName of normalizedModules) {
            moduleRegistry[moduleName] = {
                path: `${(0, moduleDiscovery_1.resolveModulesRootFromContract)(config)}/${moduleName}`,
                contract: buildDefaultModuleContractPath(moduleName, config),
                publicEntrypoints: buildDefaultModulePublicEntrypoints(moduleName, config),
            };
        }
        config.modules = moduleRegistry;
    }
    else if (Object.keys(config.modules).length === 0) {
        delete config.modules;
    }
    const components = normalizeArchitectureComponents(inputs.components);
    if (components) {
        config.components = components;
    }
    const resources = normalizeArchitectureResources(inputs.resources);
    if (resources) {
        config.resources = resources;
    }
    await saveArchitectureContract(workspaceRoot, config);
    return config;
}
async function generateDocs(workspaceRoot, config) {
    await writeFileIfMissing(path.join(workspaceRoot, 'docs', 'architecture', 'overview.md'), overviewTemplate(config));
    await writeFileIfMissing(path.join(workspaceRoot, 'docs', 'adrs', adrTemplate_1.ADR_TEMPLATE_FILE_NAME), adrTemplate_1.canonicalAdrTemplate);
    await writeFileIfMissing(path.join(workspaceRoot, 'docs', 'adrs', 'adr-001-tenant-model.md'), adrTenantModelTemplate(config));
}
async function generateContracts(workspaceRoot, config) {
    if (!hasConfiguredApi(config)) {
        return;
    }
    await writeFileIfMissing(path.join(workspaceRoot, 'contracts', 'openapi.yaml'), openApiTemplate(config));
}
async function generateDatabaseFiles(workspaceRoot, config) {
    if (!hasConfiguredDatabase(config)) {
        return;
    }
    await writeFileIfMissing(path.join(workspaceRoot, 'db', 'sql', '001_init.sql'), sqlTemplate(config));
}
async function generateArchpilotConfigFiles(workspaceRoot) {
    await writeFileIfMissing(path.join(workspaceRoot, '.archpilot', 'layer-rules.json'), defaultLayerRulesTemplate);
    await writeFileIfMissing(path.join(workspaceRoot, '.archpilot', 'dependency-rules.json'), defaultDependencyRulesTemplate);
    await writeFileIfMissing(path.join(workspaceRoot, '.archpilot', 'suppressions.json'), '{\n  "suppressions": []\n}\n');
}
async function generateArchpilotSuppressionFile(workspaceRoot) {
    await writeFileIfMissing(path.join(workspaceRoot, '.archpilot', 'suppressions.json'), '{\n  "suppressions": []\n}\n');
}
function hasArchitectureComponents(contract) {
    const components = contract.components;
    if (!components) {
        return false;
    }
    return Array.isArray(components)
        ? components.length > 0
        : Object.keys(components).length > 0;
}
function hasContractBearingInitializationUnits(contract) {
    return Object.keys(contract.modules ?? {}).length > 0 || hasArchitectureComponents(contract);
}
async function ensureArchpilotIgnoreFile(workspaceRoot) {
    return writeFileIfMissing(path.join(workspaceRoot, archpilotIgnore_1.archpilotIgnoreFileName), archpilotIgnore_1.defaultArchpilotIgnoreContent);
}
async function applyArchitectureInitialization(workspaceRoot, inputs) {
    const config = await writeArchitectureConfig(workspaceRoot, inputs);
    await generateDocs(workspaceRoot, config);
    await generateContracts(workspaceRoot, config);
    await generateDatabaseFiles(workspaceRoot, config);
    if (hasContractBearingInitializationUnits(config)) {
        const { bootstrapArchitectureConfig } = await import('./bootstrapArchitectureConfig.js');
        await bootstrapArchitectureConfig(workspaceRoot, { includeContracts: true });
        await generateArchpilotSuppressionFile(workspaceRoot);
    }
    else {
        await generateArchpilotConfigFiles(workspaceRoot);
    }
    const archpilotIgnoreFileCreated = await ensureArchpilotIgnoreFile(workspaceRoot);
    const policyInitResult = await (0, riskPolicyInitializer_1.ensureRiskPolicyFile)(workspaceRoot);
    await generateInitialArchitectureReports(workspaceRoot);
    await (0, setupNextSteps_1.refreshSetupNextStepsForWorkspace)({ workspaceRoot });
    return {
        config,
        policyFileCreated: policyInitResult.created,
        archpilotIgnoreFileCreated,
    };
}
async function generateInitialArchitectureReports(workspaceRoot) {
    const generatedAtUtc = nowUtcIso();
    const metadata = await (0, managedArtifacts_1.buildManagedMetadata)('smart-init', generatedAtUtc);
    const map = await (0, architectureMap_1.generateArchitectureMap)(workspaceRoot, {
        generatedAtUtc,
        metadata,
    });
    const reportsDir = path.join(workspaceRoot, '.archpilot', 'reports');
    await ensureDir(reportsDir);
    await Promise.all([
        writeFileIfMissing(path.join(reportsDir, 'architecture-map.json'), (0, architectureMapReporter_1.renderArchitectureMapJson)(map)),
        writeFileIfMissing(path.join(reportsDir, 'dependency-graph.json'), (0, architectureMapReporter_1.renderDependencyGraphJson)(map)),
        writeFileIfMissing(path.join(reportsDir, 'architecture-map.md'), (0, architectureMapReporter_1.renderArchitectureMapMarkdown)(map)),
        writeFileIfMissing(path.join(reportsDir, 'module-boundaries.md'), (0, architectureMapReporter_1.renderModuleBoundariesMarkdown)(map)),
    ]);
}
//# sourceMappingURL=architectureInit.js.map