/**
 * Configuration Manager for Vigthoria CLI
 */
import Conf from 'conf';
import { secureFileMode } from './cli-state.js';
const defaultConfig = {
    apiUrl: 'https://coder.vigthoria.io',
    modelsApiUrl: 'https://api.vigthoria.io', // Direct AI Models API - no proxying through Coder
    musicApiUrl: 'https://music.vigthoria.io',
    wsUrl: 'wss://coder.vigthoria.io/ws',
    selfHostedModelsApiUrl: null,
    authToken: null,
    refreshToken: null,
    userId: null,
    email: null,
    v3ServiceKey: null,
    subscription: {
        plan: null,
        status: null,
        expiresAt: null,
    },
    preferences: {
        defaultModel: 'code',
        theme: 'dark',
        autoApplyFixes: false,
        showDiffs: true,
        contextLines: 3,
        maxTokens: 4096,
    },
    persona: 'default',
    project: {
        rootPath: null,
        ignorePatterns: [
            'node_modules',
            '.git',
            'dist',
            'build',
            '__pycache__',
            '.venv',
            'venv',
            '.env',
            '*.log',
        ],
    },
};
export class Config {
    store;
    static OPERATOR_PLANS = new Set(['enterprise', 'admin', 'master_admin']);
    static CLOUD_PLANS = new Set(['pro', 'professional', 'ultra', 'enterprise', 'master_admin', 'admin']);
    constructor() {
        // `Conf` defaults to 0o644 on POSIX which would leave auth tokens
        // readable by every local user.  We post-process the file in
        // `secureOnDisk()` to enforce 0o600 ownership.  The `fileMode`
        // option exists on newer `conf` releases — supply it via a cast so
        // older type-defs do not reject the field.
        this.store = new Conf({
            projectName: 'vigthoria-cli',
            defaults: defaultConfig,
            ...{ fileMode: 0o600 },
            schema: {
                apiUrl: { type: 'string' },
                modelsApiUrl: { type: 'string' },
                musicApiUrl: { type: 'string' },
                wsUrl: { type: 'string' },
                selfHostedModelsApiUrl: { type: ['string', 'null'] },
                authToken: { type: ['string', 'null'] },
                refreshToken: { type: ['string', 'null'] },
                userId: { type: ['string', 'null'] },
                email: { type: ['string', 'null'] },
                v3ServiceKey: { type: ['string', 'null'] },
                subscription: {
                    type: 'object',
                    properties: {
                        plan: { type: ['string', 'null'] },
                        status: { type: ['string', 'null'] },
                        expiresAt: { type: ['string', 'null'] },
                    },
                },
                preferences: {
                    type: 'object',
                    properties: {
                        defaultModel: { type: 'string' },
                        theme: { type: 'string', enum: ['dark', 'light'] },
                        autoApplyFixes: { type: 'boolean' },
                        showDiffs: { type: 'boolean' },
                        contextLines: { type: 'number' },
                        maxTokens: { type: 'number' },
                    },
                },
                persona: { type: 'string', enum: ['default', 'wiener_grant'] },
                project: {
                    type: 'object',
                    properties: {
                        rootPath: { type: ['string', 'null'] },
                        ignorePatterns: { type: 'array', items: { type: 'string' } },
                    },
                },
            },
        });
        // Defence-in-depth: re-apply 0600 every time we instantiate Config so
        // that an older install which created the file with 0644 gets locked
        // down on next startup.
        try {
            secureFileMode(this.store.path);
        }
        catch { /* best-effort */ }
    }
    /**
     * Re-apply secure POSIX permissions to the on-disk config file.  Safe
     * to call repeatedly; no-op on Windows.
     */
    secureOnDisk() {
        try {
            secureFileMode(this.store.path);
        }
        catch { /* best-effort */ }
    }
    get(key) {
        return this.store.get(key);
    }
    set(key, value) {
        this.store.set(key, value);
    }
    getAll() {
        return this.store.store;
    }
    reset() {
        this.store.clear();
    }
    isAuthenticated() {
        return this.store.get('authToken') !== null;
    }
    hasValidSubscription() {
        const sub = this.store.get('subscription');
        if (!sub.status || sub.status !== 'active')
            return false;
        if (sub.expiresAt) {
            const expires = new Date(sub.expiresAt);
            return expires > new Date();
        }
        return true;
    }
    getNormalizedPlan() {
        return (this.store.get('subscription').plan || '').trim().toLowerCase();
    }
    hasOperatorAccess() {
        return Config.OPERATOR_PLANS.has(this.getNormalizedPlan());
    }
    hasCloudAccess() {
        return Config.CLOUD_PLANS.has(this.getNormalizedPlan());
    }
    getConfigPath() {
        return this.store.path;
    }
    // Auth helpers
    setAuth(data) {
        this.store.set('authToken', data.token);
        if (data.refreshToken) {
            this.store.set('refreshToken', data.refreshToken);
        }
        this.store.set('userId', data.userId);
        this.store.set('email', data.email);
        // Tighten permissions whenever the token rotates so a brand-new
        // install (which may have created the file under a previous default
        // umask) becomes 0600 immediately after first login.
        this.secureOnDisk();
    }
    clearAuth() {
        this.store.set('authToken', null);
        this.store.set('refreshToken', null);
        this.store.set('userId', null);
        this.store.set('email', null);
        this.store.set('subscription', {
            plan: null,
            status: null,
            expiresAt: null,
        });
    }
    setSubscription(data) {
        this.store.set('subscription', {
            plan: data.plan,
            status: data.status,
            expiresAt: data.expiresAt || null,
        });
    }
    // Model selection - Vigthoria Models (internal routing IDs only)
    getAvailableModels() {
        const sub = this.store.get('subscription');
        const plan = (sub.plan || '').toLowerCase();
        void plan;
        // ═══════════════════════════════════════════════════════════════
        // Vigthoria server infrastructure operational models
        // ═══════════════════════════════════════════════════════════════
        const models = [
            { id: 'code', name: 'Vigthoria v3 Code 35B', description: 'Native 35B coding model on Blackwell (V3 pipeline)', tier: 'local', backendModel: 'vigthoria-v3-code-35b' },
            { id: 'code-35b', name: 'Vigthoria v3 Code 35B', description: 'Same flagship model as code', tier: 'local', backendModel: 'vigthoria-v3-code-35b' },
            { id: 'code-9b', name: 'Vigthoria v3 Code 9B', description: 'Efficient coding specialist for quick tasks', tier: 'local', backendModel: 'vigthoria-v3-code-9b' },
            { id: 'balanced', name: 'Vigthoria Balanced 4B', description: 'Balanced general-purpose local model', tier: 'local', backendModel: 'vigthoria-v3-balanced-4b' },
            { id: 'balanced-4b', name: 'Vigthoria Balanced 4B', description: 'Efficient 4B general-purpose model (Qwen3.5-4B based)', tier: 'local', backendModel: 'vigthoria-v3-balanced-4b' },
        ];
        if (this.hasCloudAccess()) {
            models.push({ id: 'cloud-fast', name: 'Vigthoria Cloud Fast', description: 'Fast cloud responses for lighter work', tier: 'cloud', backendModel: 'vigthoria-cloud-fast' }, { id: 'cloud-balanced', name: 'Vigthoria Cloud Balanced', description: 'Default quality/cost balance for chat and coding', tier: 'cloud', backendModel: 'vigthoria-cloud-balanced' }, { id: 'cloud-code', name: 'Vigthoria Cloud Code', description: 'Economical cloud coding and completion', tier: 'cloud', backendModel: 'vigthoria-cloud-code' }, { id: 'cloud-power', name: 'Vigthoria Cloud Power', description: 'Premium general intelligence for demanding work', tier: 'cloud', backendModel: 'vigthoria-cloud-power' }, { id: 'cloud-maximum', name: 'Vigthoria Cloud Maximum', description: 'Maximum power for complex architecture and reviews', tier: 'cloud', backendModel: 'vigthoria-cloud-maximum' }, 
            // Legacy aliases
            { id: 'cloud', name: 'Vigthoria Cloud Balanced', description: 'Legacy alias for cloud-balanced', tier: 'cloud', backendModel: 'vigthoria-cloud-balanced' }, { id: 'cloud-reason', name: 'Vigthoria Cloud Balanced', description: 'Legacy alias for cloud-balanced', tier: 'cloud', backendModel: 'vigthoria-cloud-balanced' }, { id: 'ultra', name: 'Vigthoria Cloud Maximum', description: 'Legacy alias for cloud-maximum', tier: 'cloud', backendModel: 'vigthoria-cloud-maximum' });
        }
        const hubPrefs = this.store.get('hubModelPrefs');
        if (hubPrefs?.enabledCloudModels?.length) {
            return this.filterModelsByHubPreferences(models, hubPrefs.enabledCloudModels);
        }
        return models;
    }
    async refreshHubModelPreferences() {
        const token = this.store.get('authToken');
        const apiUrl = String(this.store.get('apiUrl') || '').replace(/\/$/, '');
        if (!token || !apiUrl)
            return;
        try {
            const response = await fetch(`${apiUrl}/api/user/credits/model-preferences`, {
                headers: { Authorization: `Bearer ${token}` },
                signal: AbortSignal.timeout(8000),
            });
            if (!response.ok)
                return;
            const prefs = await response.json();
            if (prefs?.success === false)
                return;
            this.store.set('hubModelPrefs', {
                enabledCloudModels: Array.isArray(prefs.enabledCloudModels) ? prefs.enabledCloudModels : [],
                defaultCloudModel: typeof prefs.defaultCloudModel === 'string' ? prefs.defaultCloudModel : undefined,
                defaultLocalModel: typeof prefs.defaultLocalModel === 'string' ? prefs.defaultLocalModel : undefined,
                balance: typeof prefs.balance === 'number' ? prefs.balance : undefined,
                fetchedAt: new Date().toISOString(),
            });
        }
        catch {
            // Non-fatal: CLI can still run with default model catalog.
        }
    }
    // Check if a model is a "Cloud" tier model
    isCloudModel(modelId) {
        const cloudModels = ['cloud-fast', 'cloud-balanced', 'cloud-code', 'cloud-power', 'cloud-maximum', 'cloud', 'cloud-reason', 'ultra'];
        return cloudModels.includes(modelId) || modelId.includes('cloud');
    }
    filterModelsByHubPreferences(models, enabledCloudModels) {
        if (!enabledCloudModels || !enabledCloudModels.length)
            return models;
        const enabled = new Set(enabledCloudModels);
        return models.filter((model) => model.tier !== 'cloud' || enabled.has(model.backendModel));
    }
    // Check if task is complex enough to suggest Cloud upgrade
    isComplexTask(prompt) {
        const complexIndicators = [
            /refactor/i, /architect/i, /redesign/i, /migrate/i,
            /multi.?file/i, /multiple files/i, /entire.*project/i,
            /all files/i, /whole.*codebase/i, /implement.*feature/i,
            /create.*system/i, /build.*from.*scratch/i,
            /analyze.*project/i, /review.*codebase/i,
            /audit.*project/i, /audit.*workspace/i,
            /full overview/i, /analyse.*workspace/i,
            /analy[sz]e.*entire/i, /deep audit/i,
        ];
        return complexIndicators.some(pattern => pattern.test(prompt));
    }
    shouldUseCloudForHeavyTask(prompt) {
        // DISABLED: Cloud routing is now EXPLICIT ONLY (--model cloud or /cloud command)
        // Do NOT auto-route based on keywords. User must opt-in.
        // If user wants cloud: they'll use --model cloud or request it explicitly.
        void prompt;
        return false;
    }
}
