import * as vscode from 'vscode';
import { ACTIONS, ACTION_LABELS, MIN_SELECTION_LENGTH, type ActionId } from '@lib/actions';
import type { LexAIRunAction } from './session';

let refreshSelection: (() => void) | undefined;

/** Force CodeLens refresh (e.g. right after activation). */
export function refreshSelectionAffordance(): void {
  refreshSelection?.();
}

/**
 * Selection affordance: CodeLens on the first selected line.
 * Click LexAI → expands into action lenses *on that same line*.
 */
export function registerSelectionAffordance(
  context: vscode.ExtensionContext,
  onPickAction: (action: LexAIRunAction) => void | Promise<void>,
): void {
  const codeLensEmitter = new vscode.EventEmitter<void>();
  let active: { uri: vscode.Uri; line: number; selected: boolean } | undefined;
  let menuOpen = false;

  const collapseMenu = () => {
    if (!menuOpen) return;
    menuOpen = false;
    codeLensEmitter.fire();
  };

  const refresh = (editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor) => {
    if (!editor) {
      active = undefined;
      menuOpen = false;
      void vscode.commands.executeCommand('setContext', 'lexai.hasSelection', false);
      codeLensEmitter.fire();
      return;
    }

    const sel = editor.selection;
    const text = editor.document.getText(sel);
    const selected = !sel.isEmpty && text.trim().length >= MIN_SELECTION_LENGTH;

    void vscode.commands.executeCommand('setContext', 'lexai.hasSelection', selected);

    if (!selected) {
      active = undefined;
      menuOpen = false;
      codeLensEmitter.fire();
      return;
    }

    const line = sel.start.line;
    if (active && (active.uri.toString() !== editor.document.uri.toString() || active.line !== line)) {
      menuOpen = false;
    }
    active = { uri: editor.document.uri, line, selected: true };
    codeLensEmitter.fire();
  };

  refreshSelection = () => refresh(vscode.window.activeTextEditor);

  context.subscriptions.push(
    codeLensEmitter,
    { dispose: () => { refreshSelection = undefined; } },
    vscode.window.onDidChangeActiveTextEditor((e) => refresh(e)),
    vscode.window.onDidChangeTextEditorSelection((e) => {
      if (e.textEditor === vscode.window.activeTextEditor) refresh(e.textEditor);
    }),
    vscode.workspace.onDidChangeTextDocument((e) => {
      const ed = vscode.window.activeTextEditor;
      if (ed && e.document === ed.document) refresh(ed);
    }),
    vscode.languages.registerCodeLensProvider({ scheme: '*' }, {
      onDidChangeCodeLenses: codeLensEmitter.event,
      provideCodeLenses(document) {
        if (!active?.selected || active.uri.toString() !== document.uri.toString()) {
          return [];
        }
        const range = new vscode.Range(active.line, 0, active.line, 0);

        if (!menuOpen) {
          return [
            new vscode.CodeLens(range, {
              title: '$(sparkle) LexAI',
              tooltip: 'Show LexAI actions here',
              command: 'lexai.toggleSelectionMenu',
            }),
          ];
        }

        return [
          new vscode.CodeLens(range, {
            title: '$(sparkle) LexAI',
            tooltip: 'Collapse',
            command: 'lexai.toggleSelectionMenu',
          }),
          new vscode.CodeLens(range, {
            title: '$(code) Code Assist',
            tooltip: 'Describe what to do with the selection (workspace-aware)',
            command: 'lexai.runSelectionAction',
            arguments: ['codeAssist'],
          }),
          ...ACTIONS.map(
            (id) =>
              new vscode.CodeLens(range, {
                title: ACTION_LABELS[id],
                tooltip: `Run ${ACTION_LABELS[id]}`,
                command: 'lexai.runSelectionAction',
                arguments: [id],
              }),
          ),
          new vscode.CodeLens(range, {
            title: '$(close)',
            tooltip: 'Close menu',
            command: 'lexai.toggleSelectionMenu',
          }),
        ];
      },
    }),
    vscode.commands.registerCommand('lexai.toggleSelectionMenu', () => {
      if (!active?.selected) return;
      menuOpen = !menuOpen;
      codeLensEmitter.fire();
    }),
    vscode.commands.registerCommand(
      'lexai.runSelectionAction',
      async (action: LexAIRunAction) => {
        collapseMenu();
        await onPickAction(action);
      },
    ),
    vscode.commands.registerCommand('lexai.showSelectionActions', () => {
      if (!active?.selected) {
        void vscode.window.showInformationMessage('LexAI: select some text first.');
        return;
      }
      menuOpen = true;
      codeLensEmitter.fire();
    }),
  );

  refresh(vscode.window.activeTextEditor);
}
