/**
 * Mock VS Code API for testing.
 * Provides minimal implementation of vscode module needed for tests.
 */

class Range {
    constructor(startLine, startChar, endLine, endChar) {
        this.start = { line: startLine, character: startChar };
        this.end = { line: endLine, character: endChar };
    }
}

class Position {
    constructor(line, character) {
        this.line = line;
        this.character = character;
    }
    
    translate(lineDelta, characterDelta = 0) {
        return new Position(this.line + lineDelta, this.character + characterDelta);
    }
}

class Diagnostic {
    constructor(range, message, severity) {
        this.range = range;
        this.message = message;
        this.severity = severity;
    }
}

class DiagnosticSeverity {
    static Error = 0;
    static Warning = 1;
    static Information = 2;
    static Hint = 3;
}

class CodeActionKind {
    static QuickFix = 'quickfix';
    static Refactor = 'refactor';
    static RefactorExtract = 'refactor.extract';
    static RefactorInline = 'refactor.inline';
    static RefactorRewrite = 'refactor.rewrite';
    static Source = 'source';
    static SourceFixAll = 'source.fixAll';
    static SourceOrganizeImports = 'source.organizeImports';
}

class CodeAction {
    constructor(title, kind) {
        this.title = title;
        this.kind = kind;
        this.edit = null;
        this.diagnostics = [];
    }
}

class WorkspaceEdit {
    constructor() {
        this.edits = new Map();
    }
    
    replace(uri, range, newText) {
        if (!this.edits.has(uri)) {
            this.edits.set(uri, []);
        }
        this.edits.get(uri).push({ range, newText });
    }
    
    insert(uri, position, newText) {
        if (!this.edits.has(uri)) {
            this.edits.set(uri, []);
        }
        this.edits.get(uri).push({ position, newText });
    }
    
    delete(uri, range) {
        if (!this.edits.has(uri)) {
            this.edits.set(uri, []);
        }
        this.edits.get(uri).push({ range, newText: '' });
    }
}

class MarkdownString {
    constructor(value) {
        this.value = value || '';
        this.isTrusted = false;
        this.supportThemeIcons = false;
    }
    
    appendMarkdown(value) {
        this.value += value;
        return this;
    }
    
    appendCodeblock(value, language) {
        this.value += `\`\`\`${language || ''}\n${value}\n\`\`\`\n`;
        return this;
    }
}

class CompletionItem {
    constructor(label, kind) {
        this.label = label;
        this.kind = kind;
        this.insertText = undefined;
        this.detail = undefined;
        this.documentation = undefined;
        this.sortText = undefined;
        this.filterText = undefined;
    }
}

class CompletionItemKind {
    static Function = 3;
    static GlobalVariable = 20;
}

class SnippetString {
    constructor(value) {
        this.value = value || "";
    }
}

class Uri {
    constructor(scheme, path) {
        this.scheme = scheme;
        this.path = path;
        this.fsPath = path;
    }
    
    static file(path) {
        return new Uri('file', path);
    }
    
    toString() {
        return `${this.scheme}://${this.path}`;
    }
}

class Location {
    constructor(uri, range) {
        this.uri = uri;
        this.range = range;
    }
}

class SemanticTokensLegend {
    constructor(tokenTypes, tokenModifiers) {
        this.tokenTypes = tokenTypes;
        this.tokenModifiers = tokenModifiers;
    }
}

class SemanticTokensBuilder {
    constructor(_legend) {
        this._tokens = [];
    }

    push(line, char, length, tokenType, tokenModifiers) {
        this._tokens.push({ line, char, length, tokenType, tokenModifiers });
    }

    build() {
        return { data: this._tokens };
    }
}

const languages = {
    createDiagnosticCollection: (name) => ({
        name,
        set: () => {},
        delete: () => {},
        clear: () => {},
        dispose: () => {}
    }),
    registerHoverProvider: () => ({ dispose: () => {} }),
    registerCompletionItemProvider: () => ({ dispose: () => {} }),
    registerDefinitionProvider: () => ({ dispose: () => {} }),
    registerCodeActionsProvider: () => ({ dispose: () => {} }),
    registerDocumentSemanticTokensProvider: () => ({ dispose: () => {} })
};

// Per-spec config overrides: keyed as "section.key" → value.
// Set before collectDiagnostics and cleared after via workspace.setConfigOverride / clearConfigOverrides.
const _configOverrides = {};

const workspace = {
    getConfiguration: (section) => ({
        // Return section-specific overrides for test environment defaults.
        // Notes: robodoc unit tests mock getRobodocConfig() directly, so this only
        // affects syntax test fixtures that run through the real collectDiagnostics path.
        get: (key, defaultValue) => {
            const overrideKey = `${section}.${key}`;
            if (overrideKey in _configOverrides) return _configOverrides[overrideKey];
            if (section === "acurity.robodoc" && key === "requireDocBlock") return false;
            return defaultValue;
        }
    }),
    setConfigOverride: (section, key, value) => {
        _configOverrides[`${section}.${key}`] = value;
    },
    clearConfigOverrides: () => {
        Object.keys(_configOverrides).forEach((k) => delete _configOverrides[k]);
    },
    onDidOpenTextDocument: () => ({ dispose: () => {} }),
    onDidChangeTextDocument: () => ({ dispose: () => {} }),
    onDidCloseTextDocument: () => ({ dispose: () => {} }),
    getWorkspaceFolder: () => null,
    textDocuments: [],
    openTextDocument: async (uri) => {
        throw new Error('openTextDocument not mocked for this test');
    }
};

export {
    Range,
    Position,
    Diagnostic,
    DiagnosticSeverity,
    CodeActionKind,
    CodeAction,
    WorkspaceEdit,
    MarkdownString,
    CompletionItem,
    CompletionItemKind,
    SnippetString,
    Uri,
    Location,
    SemanticTokensLegend,
    SemanticTokensBuilder,
    languages,
    workspace
};
