import { existsSync, writeFileSync, mkdirSync } from 'node:fs';
import { stringify } from 'yaml';
import { ProjectConfigSchema } from '../../../core/models/index.js';
import { copyProjectResourcesToDir } from '../../resources/index.js';
import { normalizeConfigProviderReference, } from '../providerReference.js';
import { normalizePipelineConfig, normalizeProviderProfiles, denormalizeProviderProfiles, denormalizeProviderOptions, denormalizePersonaProviders, normalizePersonaProviders, normalizeTaktProviders, buildRawTaktProvidersOrThrow, normalizeAssistantConfig, denormalizeAssistantConfig, normalizeWorkflowOverrides, denormalizeWorkflowOverrides, normalizeRuntime, normalizeRateLimitFallback, denormalizeRateLimitFallback, } from '../configNormalizers.js';
import { resolveAliasedPreviewCount, } from '../configKeyAliases.js';
import { invalidateResolvedConfigCache } from '../resolutionCache.js';
import { expandOptionalHomePath } from '../pathExpansion.js';
import { getProjectConfigDir, getProjectConfigPath } from './projectConfigPaths.js';
import { normalizeSubmodules, normalizeWithSubmodules, normalizeAnalytics, denormalizeAnalytics, normalizeWorkflowRuntimePreparePolicy, denormalizeWorkflowRuntimePreparePolicy, normalizeWorkflowCommandGatesPolicy, denormalizeWorkflowCommandGatesPolicy, normalizeWorkflowArpeggioPolicy, denormalizeWorkflowArpeggioPolicy, normalizeSyncConflictResolver, denormalizeSyncConflictResolver, normalizeWorkflowMcpServers, denormalizeWorkflowMcpServers, } from './projectConfigTransforms.js';
import { denormalizeObservabilityConfig, normalizeObservabilityConfig, } from '../observabilityConfig.js';
import { loadProjectConfigTrace } from '../traced/tracedConfigLoader.js';
import { getCachedProjectConfigTrace, setCachedProjectConfigTrace } from '../resolutionCache.js';
import { assertValidProjectConfig } from './projectConfigValidation.js';
export function loadProjectConfig(projectDir) {
    const configPath = getProjectConfigPath(projectDir);
    const { parsedConfig, rawConfig, trace } = loadProjectConfigTrace(configPath);
    setCachedProjectConfigTrace(projectDir, trace);
    assertValidProjectConfig(parsedConfig, configPath, true);
    assertValidProjectConfig(rawConfig, configPath);
    const parsedConfigResult = ProjectConfigSchema.parse(rawConfig);
    const { language, provider, model, allow_git_hooks, allow_git_filters, auto_pr, draft_pr, vcs_provider, base_branch, submodules, with_submodules, provider_options, analytics, pipeline, assistant, takt_providers, persona_providers, branch_name_strategy, minimal_output, concurrency, task_poll_interval_ms, runtime, rate_limit_fallback, sync_project_local_takt_on_retry, sync_conflict_resolver, observability, } = parsedConfigResult;
    const normalizedProvider = normalizeConfigProviderReference(provider, model, provider_options);
    const normalizedSubmodules = normalizeSubmodules(submodules);
    const normalizedWithSubmodules = normalizeWithSubmodules(with_submodules);
    const effectiveWithSubmodules = normalizedSubmodules === undefined ? normalizedWithSubmodules : undefined;
    const normalizedPipeline = normalizePipelineConfig(pipeline);
    const normalizedPersonaProviders = normalizePersonaProviders(persona_providers);
    const analyticsConfig = normalizeAnalytics(analytics);
    const normalizedTaktProviders = normalizeTaktProviders(takt_providers);
    return {
        language: language,
        pipeline: normalizedPipeline,
        assistant: normalizeAssistantConfig(assistant),
        taktProviders: normalizedTaktProviders,
        personaProviders: normalizedPersonaProviders,
        branchNameStrategy: branch_name_strategy,
        minimalOutput: minimal_output,
        concurrency: concurrency,
        taskPollIntervalMs: task_poll_interval_ms,
        interactivePreviewSteps: resolveAliasedPreviewCount(parsedConfigResult),
        syncProjectLocalTaktOnRetry: sync_project_local_takt_on_retry,
        allowGitHooks: allow_git_hooks,
        allowGitFilters: allow_git_filters,
        autoPr: auto_pr,
        draftPr: draft_pr,
        vcsProvider: vcs_provider,
        baseBranch: base_branch,
        submodules: normalizedSubmodules,
        withSubmodules: effectiveWithSubmodules,
        analytics: analyticsConfig ? {
            ...analyticsConfig,
            eventsPath: expandOptionalHomePath(analyticsConfig.eventsPath),
        } : undefined,
        observability: normalizeObservabilityConfig(observability),
        provider: normalizedProvider.provider,
        model: normalizedProvider.model,
        providerOptions: normalizedProvider.providerOptions,
        rateLimitFallback: normalizeRateLimitFallback(rate_limit_fallback),
        providerProfiles: normalizeProviderProfiles(parsedConfigResult.provider_profiles),
        workflowOverrides: normalizeWorkflowOverrides(parsedConfigResult.workflow_overrides),
        runtime: normalizeRuntime(runtime),
        workflowRuntimePrepare: normalizeWorkflowRuntimePreparePolicy(parsedConfigResult.workflow_runtime_prepare),
        workflowCommandGates: normalizeWorkflowCommandGatesPolicy(parsedConfigResult.workflow_command_gates),
        workflowArpeggio: normalizeWorkflowArpeggioPolicy(parsedConfigResult.workflow_arpeggio),
        syncConflictResolver: normalizeSyncConflictResolver(sync_conflict_resolver),
        workflowMcpServers: normalizeWorkflowMcpServers(parsedConfigResult.workflow_mcp_servers),
    };
}
export function loadProjectConfigTraceState(projectDir) {
    const cached = getCachedProjectConfigTrace(projectDir);
    if (cached) {
        return cached;
    }
    loadProjectConfig(projectDir);
    const trace = getCachedProjectConfigTrace(projectDir);
    if (!trace) {
        throw new Error(`Project config trace is not available for ${projectDir}`);
    }
    return trace;
}
export function saveProjectConfig(projectDir, config) {
    const configDir = getProjectConfigDir(projectDir);
    const configPath = getProjectConfigPath(projectDir);
    if (!existsSync(configDir)) {
        mkdirSync(configDir, { recursive: true });
    }
    copyProjectResourcesToDir(configDir);
    const savePayload = { ...config };
    const normalizedSubmodules = normalizeSubmodules(config.submodules);
    const rawAnalytics = denormalizeAnalytics(config.analytics);
    if (rawAnalytics) {
        savePayload.analytics = rawAnalytics;
    }
    else {
        delete savePayload.analytics;
    }
    const rawObservability = denormalizeObservabilityConfig(config.observability);
    if (rawObservability) {
        savePayload.observability = rawObservability;
    }
    else {
        delete savePayload.observability;
    }
    const rawProfiles = denormalizeProviderProfiles(config.providerProfiles);
    if (rawProfiles && Object.keys(rawProfiles).length > 0) {
        savePayload.provider_profiles = rawProfiles;
    }
    else {
        delete savePayload.provider_profiles;
    }
    const rawProviderOptions = denormalizeProviderOptions(config.providerOptions);
    if (rawProviderOptions) {
        savePayload.provider_options = rawProviderOptions;
    }
    else {
        delete savePayload.provider_options;
    }
    const rawRateLimitFallback = denormalizeRateLimitFallback(config.rateLimitFallback);
    if (rawRateLimitFallback) {
        savePayload.rate_limit_fallback = rawRateLimitFallback;
    }
    else {
        delete savePayload.rate_limit_fallback;
    }
    for (const [camel, snake] of [['language', 'language'], ['autoPr', 'auto_pr'], ['draftPr', 'draft_pr'], ['allowGitHooks', 'allow_git_hooks'], ['allowGitFilters', 'allow_git_filters'], ['vcsProvider', 'vcs_provider'], ['baseBranch', 'base_branch'], ['branchNameStrategy', 'branch_name_strategy'], ['minimalOutput', 'minimal_output'], ['taskPollIntervalMs', 'task_poll_interval_ms'], ['interactivePreviewSteps', 'interactive_preview_steps'], ['syncProjectLocalTaktOnRetry', 'sync_project_local_takt_on_retry'], ['concurrency', 'concurrency']]) {
        if (config[camel] !== undefined)
            savePayload[snake] = config[camel];
    }
    delete savePayload.pipeline;
    if (config.pipeline) {
        const pr = {};
        if (config.pipeline.defaultBranchPrefix !== undefined)
            pr.default_branch_prefix = config.pipeline.defaultBranchPrefix;
        if (config.pipeline.commitMessageTemplate !== undefined)
            pr.commit_message_template = config.pipeline.commitMessageTemplate;
        if (config.pipeline.prBodyTemplate !== undefined)
            pr.pr_body_template = config.pipeline.prBodyTemplate;
        if (Object.keys(pr).length > 0)
            savePayload.pipeline = pr;
    }
    const rawPersonaProviders = denormalizePersonaProviders(config.personaProviders);
    if (rawPersonaProviders && Object.keys(rawPersonaProviders).length > 0) {
        savePayload.persona_providers = rawPersonaProviders;
    }
    else {
        delete savePayload.persona_providers;
    }
    const rawTaktProviders = buildRawTaktProvidersOrThrow(config.taktProviders);
    if (rawTaktProviders) {
        savePayload.takt_providers = rawTaktProviders;
    }
    else {
        delete savePayload.takt_providers;
    }
    const rawAssistant = denormalizeAssistantConfig(config.assistant);
    if (rawAssistant) {
        savePayload.assistant = rawAssistant;
    }
    else {
        delete savePayload.assistant;
    }
    if (normalizedSubmodules !== undefined) {
        savePayload.submodules = normalizedSubmodules;
        delete savePayload.with_submodules;
    }
    else {
        delete savePayload.submodules;
        if (config.withSubmodules !== undefined) {
            savePayload.with_submodules = config.withSubmodules;
        }
        else {
            delete savePayload.with_submodules;
        }
    }
    for (const k of ['providerProfiles', 'providerOptions', 'rateLimitFallback', 'autoPr', 'draftPr', 'allowGitHooks', 'allowGitFilters', 'vcsProvider', 'baseBranch', 'withSubmodules', 'branchNameStrategy', 'minimalOutput', 'taskPollIntervalMs', 'interactivePreviewSteps', 'syncProjectLocalTaktOnRetry', 'personaProviders', 'taktProviders', 'workflowRuntimePrepare', 'workflowCommandGates', 'workflowArpeggio', 'syncConflictResolver', 'workflowMcpServers']) {
        delete savePayload[k];
    }
    const rawWorkflowOverrides = denormalizeWorkflowOverrides(config.workflowOverrides);
    if (rawWorkflowOverrides) {
        savePayload.workflow_overrides = rawWorkflowOverrides;
    }
    delete savePayload.workflowOverrides;
    const normalizedRuntime = normalizeRuntime(config.runtime);
    if (normalizedRuntime) {
        savePayload.runtime = normalizedRuntime;
    }
    else {
        delete savePayload.runtime;
    }
    for (const [key, raw] of [['workflow_runtime_prepare', denormalizeWorkflowRuntimePreparePolicy(config.workflowRuntimePrepare)], ['workflow_command_gates', denormalizeWorkflowCommandGatesPolicy(config.workflowCommandGates)], ['workflow_arpeggio', denormalizeWorkflowArpeggioPolicy(config.workflowArpeggio)], ['sync_conflict_resolver', denormalizeSyncConflictResolver(config.syncConflictResolver)], ['workflow_mcp_servers', denormalizeWorkflowMcpServers(config.workflowMcpServers)]]) {
        if (raw) {
            savePayload[key] = raw;
        }
        else {
            delete savePayload[key];
        }
    }
    const content = stringify(savePayload, { indent: 2 });
    writeFileSync(configPath, content, 'utf-8');
    invalidateResolvedConfigCache(projectDir);
}
export function updateProjectConfig(projectDir, key, value) {
    const config = loadProjectConfig(projectDir);
    config[key] = value;
    saveProjectConfig(projectDir, config);
}
//# sourceMappingURL=projectConfig.js.map