/**
 * LaTeX Hover Provider for Monaco Editor.
 * Provides documentation on hover for LaTeX commands and environments.
 */
import type * as Monaco from 'monaco-editor';
import {
    COMMAND_MAP,
    ENVIRONMENT_MAP,
    type LaTeXCommand,
    type LaTeXEnvironment,
} from './commands/data';

export class LaTeXHoverProvider implements Monaco.languages.HoverProvider {
    constructor(private monaco: typeof Monaco) {}

    provideHover(
        model: Monaco.editor.ITextModel,
        position: Monaco.Position,
        token: Monaco.CancellationToken
    ): Monaco.languages.ProviderResult<Monaco.languages.Hover> {
        const word = model.getWordAtPosition(position);
        if (!word) return null;

        const lineContent = model.getLineContent(position.lineNumber);
        const beforeWord = lineContent.substring(0, word.startColumn - 1);

        // Check if this is a LaTeX command (preceded by backslash)
        if (beforeWord.endsWith('\\')) {
            const command = COMMAND_MAP.get(word.word);
            if (command) {
                return this.createCommandHover(command, {
                    startLineNumber: position.lineNumber,
                    startColumn: word.startColumn - 1, // Include the backslash
                    endLineNumber: position.lineNumber,
                    endColumn: word.endColumn,
                });
            }
        }

        // Check if it's an environment name inside \begin{} or \end{}
        const envMatch = lineContent.match(/\\(begin|end)\{(\w+\*?)\}/);
        if (envMatch && word.word === envMatch[2]) {
            const env = ENVIRONMENT_MAP.get(envMatch[2]);
            if (env) {
                return this.createEnvironmentHover(env, {
                    startLineNumber: position.lineNumber,
                    startColumn: word.startColumn,
                    endLineNumber: position.lineNumber,
                    endColumn: word.endColumn,
                });
            }
        }

        return null;
    }

    private createCommandHover(
        cmd: LaTeXCommand,
        range: Monaco.IRange
    ): Monaco.languages.Hover {
        const contents: Monaco.IMarkdownString[] = [];

        // Command signature
        if (cmd.signature) {
            contents.push({
                value: `\`\\${cmd.name}${cmd.signature}\``,
            });
        } else {
            contents.push({
                value: `\`\\${cmd.name}\``,
            });
        }

        // Description
        contents.push({
            value: cmd.description,
        });

        // Category
        contents.push({
            value: `*Category:* ${cmd.category}`,
        });

        // Package requirement
        if (cmd.package) {
            contents.push({
                value: `*Requires:* \`\\usepackage{${cmd.package}}\``,
            });
        }

        // Example
        if (cmd.example) {
            contents.push({
                value: `**Example:**\n\`\`\`latex\n${cmd.example}\n\`\`\``,
            });
        }

        return { contents, range };
    }

    private createEnvironmentHover(
        env: LaTeXEnvironment,
        range: Monaco.IRange
    ): Monaco.languages.Hover {
        const contents: Monaco.IMarkdownString[] = [];

        // Environment name
        contents.push({
            value: `\`\\begin{${env.name}}...\\end{${env.name}}\``,
        });

        // Description
        contents.push({
            value: env.description,
        });

        // Category
        contents.push({
            value: `*Category:* ${env.category}`,
        });

        // Package requirement
        if (env.package) {
            contents.push({
                value: `*Requires:* \`\\usepackage{${env.package}}\``,
            });
        }

        return { contents, range };
    }
}

/**
 * Creates a hover provider for LaTeX.
 */
export function createHoverProvider(monaco: typeof Monaco): LaTeXHoverProvider {
    return new LaTeXHoverProvider(monaco);
}
