/*
 * Copyright 2026, Jaime Terrats.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { Messages } from '@salesforce/core';
import { Flags, SfCommand } from '@salesforce/sf-plugins-core';
import { applyActivationBlock } from '../../generators/claude-generator.js';
import { ALL_PROFILES } from '../../profiles/index.js';
import { checkCoreDependencies, checkRuntimeDependencies, formatMissingDependencies, } from '../../services/dependency-check.js';
import { buildWorkspaceConfig, validateWorkspaceConfig, writeWorkspaceConfig, } from '../../services/workspace-config.js';
import { touchWorkspace } from '../../services/workspace-registry.js';
import { SUPPORTED_TOOLS } from '../../types/index.js';
import { detectTools, resolveProfiles } from '../../util/command-helpers.js';
import { PLUGIN_VERSION } from '../../version.js';
import Local from './local.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@jterrats/setup-agents', 'setup-agents.init');
const PROFILE_HELP_VALUE = ALL_PROFILES.map((profile) => profile.id).join('|');
const MODE_OPTIONS = ['project', 'advisory'];
export default class Init extends SfCommand {
    static summary = messages.getMessage('summary');
    static description = messages.getMessage('description');
    static examples = messages.getMessages('examples');
    static flags = {
        mode: Flags.string({
            summary: messages.getMessage('flags.mode.summary'),
            description: messages.getMessage('flags.mode.description'),
            options: MODE_OPTIONS,
            default: 'project',
        }),
        advisory: Flags.boolean({
            summary: messages.getMessage('flags.advisory.summary'),
            description: messages.getMessage('flags.advisory.description'),
            default: false,
        }),
        profile: Flags.string({
            summary: messages.getMessage('flags.profile.summary'),
            description: messages.getMessage('flags.profile.description'),
            helpValue: PROFILE_HELP_VALUE,
        }),
        tools: Flags.string({
            summary: messages.getMessage('flags.tools.summary'),
            description: messages.getMessage('flags.tools.description'),
            helpValue: SUPPORTED_TOOLS.join('|'),
        }),
        force: Flags.boolean({
            char: 'f',
            summary: messages.getMessage('flags.force.summary'),
            description: messages.getMessage('flags.force.description'),
            default: false,
        }),
        commit: Flags.boolean({
            summary: messages.getMessage('flags.commit.summary'),
            description: messages.getMessage('flags.commit.description'),
            default: false,
        }),
        'dry-run': Flags.boolean({
            summary: messages.getMessage('flags.dry-run.summary'),
            description: messages.getMessage('flags.dry-run.description'),
            default: false,
        }),
        quick: Flags.boolean({
            summary: messages.getMessage('flags.quick.summary'),
            description: messages.getMessage('flags.quick.description'),
            default: false,
        }),
    };
    async run() {
        const { flags } = await this.parse(Init);
        const cwd = process.cwd();
        const mode = flags.advisory ? 'advisory' : flags.mode;
        const quickMode = flags.quick;
        const profileFlag = this.resolveProfileFlag(cwd, quickMode, flags.profile);
        const { profiles, usedDefault } = await resolveProfiles(cwd, profileFlag, messages, (msg) => this.warn(msg));
        const tools = flags.tools ? this.resolveTools(flags.tools) : detectTools(cwd);
        this.checkDependencies();
        const config = buildWorkspaceConfig({ mode, profiles, tools });
        this.warnOnValidationErrors(config);
        const result = writeWorkspaceConfig(cwd, config, { force: flags.force || quickMode });
        this.handleConfigResult(result, cwd);
        if (usedDefault)
            this.warn(messages.getMessage('warn.profileDefault'));
        this.log(messages.getMessage('info.done', [mode, profiles.map((profile) => profile.id).join(', '), tools.join(', ')]));
        this.writeActivationBlocks(cwd, tools, flags['dry-run'] ?? false);
        if (flags.commit)
            writeTeamSetupNote(cwd, messages, (msg) => this.log(msg));
        await this.maybeRunLocal(result.written, flags['dry-run'] ?? false, flags.force, quickMode);
        return { configFile: result.path, config, written: result.written, cwd };
    }
    resolveProfileFlag(cwd, quickMode, flagProfile) {
        if (quickMode && !flagProfile) {
            return this.autoDetectProfiles(cwd).join(',') || undefined;
        }
        return flagProfile;
    }
    warnOnValidationErrors(config) {
        const validation = validateWorkspaceConfig(config);
        if (validation.valid)
            return;
        for (const error of validation.errors)
            this.warn(error);
        for (const guidance of validation.guidance)
            this.warn(guidance);
    }
    async maybeRunLocal(written, dryRun, force, quickMode) {
        if (!written || dryRun)
            return;
        if (!quickMode && (force || !process.stdin.isTTY))
            return;
        this.log(messages.getMessage('info.runningLocal'));
        const localArgs = ['--force'];
        if (quickMode)
            localArgs.push('--quick');
        await Local.run(localArgs);
    }
    handleConfigResult(result, cwd) {
        if (result.written) {
            this.log(messages.getMessage('info.fileCreated', [result.path]));
            try {
                touchWorkspace(cwd);
            }
            catch {
                /* non-critical */
            }
        }
        else {
            this.warn(messages.getMessage('warn.fileExists', [result.path]));
        }
    }
    checkDependencies() {
        const coreCheck = checkCoreDependencies();
        if (coreCheck.missing.length > 0) {
            this.warn(formatMissingDependencies(coreCheck.missing));
        }
        const runtimeCheck = checkRuntimeDependencies();
        if (runtimeCheck.installed.length === 0) {
            this.warn('No AI runtime detected (claude, codex, or cursor). Workflow execution will not work until one is installed.');
        }
    }
    writeActivationBlocks(cwd, tools, dryRun) {
        if (tools.includes('claude')) {
            writeActivationBlock(cwd, 'CLAUDE.md', dryRun, (msg) => this.log(msg));
        }
        if (tools.includes('codex')) {
            writeActivationBlock(cwd, 'AGENTS.md', dryRun, (msg) => this.log(msg));
        }
    }
    // eslint-disable-next-line class-methods-use-this
    autoDetectProfiles(cwd) {
        return ALL_PROFILES.filter((p) => p.detect?.(cwd)).map((p) => p.id);
    }
    resolveTools(flagValue) {
        const requested = flagValue.split(',').map((tool) => tool.trim());
        const invalid = requested.filter((tool) => !SUPPORTED_TOOLS.includes(tool));
        if (invalid.length > 0) {
            this.warn(messages.getMessage('warn.unknownTools', [invalid.join(', '), SUPPORTED_TOOLS.join(', ')]));
        }
        return SUPPORTED_TOOLS.filter((tool) => requested.includes(tool));
    }
}
const TEAM_SETUP_BLOCK_START = '<!-- setup-agents:team-setup -->';
const TEAM_SETUP_BLOCK_END = '<!-- /setup-agents:team-setup -->';
const TEAM_SETUP_CONTENT = [
    TEAM_SETUP_BLOCK_START,
    '',
    '## Team Setup',
    '',
    'This project uses [setup-agents](https://github.com/jterrats/setup-agents) to configure AI coding assistant rules.',
    '',
    'After cloning, run:',
    '',
    '```sh',
    'sf setup-agents local',
    '```',
    '',
    'This reads `.setup-agents/config.json` and generates the AI rule files for your tools automatically.',
    '',
    TEAM_SETUP_BLOCK_END,
].join('\n');
function writeActivationBlock(cwd, filename, dryRun, log) {
    const filePath = join(cwd, filename);
    const existing = existsSync(filePath) ? readFileSync(filePath, 'utf8') : '';
    const updated = applyActivationBlock(existing, PLUGIN_VERSION);
    if (updated === existing)
        return;
    if (dryRun) {
        log(`[dry-run] Would update ${filename} with setup-agents activation block`);
        return;
    }
    writeFileSync(filePath, updated, 'utf8');
    log(`Updated ${filename} with setup-agents activation block`);
}
function writeTeamSetupNote(cwd, msgs, log) {
    const readmePath = join(cwd, 'README.md');
    if (existsSync(readmePath)) {
        const existing = readFileSync(readmePath, 'utf8');
        if (existing.includes(TEAM_SETUP_BLOCK_START))
            return;
        writeFileSync(readmePath, `${existing.trimEnd()}\n\n${TEAM_SETUP_CONTENT}\n`, 'utf8');
        log(msgs.getMessage('info.readmeUpdated', [readmePath]));
    }
    else {
        writeFileSync(readmePath, `${TEAM_SETUP_CONTENT}\n`, 'utf8');
        log(msgs.getMessage('info.readmeCreated', [readmePath]));
    }
}
//# sourceMappingURL=init.js.map