/**
 * Formatting/style composable — handles paragraph-style application,
 * the `applyFormatting` ref-API entry point that maps an agent's mark
 * toggle request to a PM transaction, page break insertion, symbol
 * insertion, and clear-formatting.
 */

import type { Ref } from 'vue';
import type { EditorView } from 'prosemirror-view';
import type { Document } from '@eigenpal/docx-editor-core/types/document';
import { applyStyle } from '@eigenpal/docx-editor-core/prosemirror/commands/paragraph';
import { createStyleResolver } from '@eigenpal/docx-editor-core/prosemirror/styles';
import { getCachedNumberingMap } from '@eigenpal/docx-editor-core/docx';
import { clearFormatting } from '@eigenpal/docx-editor-core/prosemirror/commands/formatting';
import { insertPageBreak } from '@eigenpal/docx-editor-core/prosemirror/commands/pageBreak';
import {
  insertSectionBreakNextPage,
  insertSectionBreakContinuous,
} from '@eigenpal/docx-editor-core/prosemirror/commands/sectionBreak';
import {
  applyFormatting as applyFormattingCore,
  setParagraphStyle as setParagraphStyleCore,
  insertBreak as insertBreakCore,
  type ApplyFormattingOptions,
  type InsertBreakOptions,
} from '@eigenpal/docx-editor-core/prosemirror/applyFormatting';

export interface UseFormattingActionsOptions {
  editorView: Ref<EditorView | null>;
  /**
   * The view interactive toolbar formatting should target. While a header or
   * footer is being edited this is its EditorView, so toolbar actions land in
   * the HF and not the body (#749). Falls back to the body `editorView`. The
   * agent ref-API (`applyFormatting`/`setParagraphStyle`, which resolve a
   * paraId in the body) deliberately keeps using `editorView`.
   */
  activeView?: Ref<EditorView | null>;
  getDocument: () => Document | null;
}

export type { ApplyFormattingOptions, InsertBreakOptions };

export function useFormattingActions(opts: UseFormattingActionsOptions) {
  const targetView = () => opts.activeView?.value ?? opts.editorView.value;

  function handleClearFormatting() {
    const view = targetView();
    if (!view) return;
    clearFormatting(view.state, view.dispatch, view);
    view.focus();
  }

  function handleApplyStyle(styleId: string) {
    const view = targetView();
    if (!view) return;
    const doc = opts.getDocument();
    const styles = doc?.package?.styles;
    if (styles) {
      const resolver = createStyleResolver(styles);
      const resolved = resolver.resolveParagraphStyle(styleId);
      applyStyle(styleId, {
        paragraphFormatting: resolved.paragraphFormatting,
        runFormatting: resolved.runFormatting,
        numbering: doc?.package?.numbering ? getCachedNumberingMap(doc.package.numbering) : null,
      })(view.state, (tr) => view.dispatch(tr));
    } else {
      applyStyle(styleId)(view.state, (tr) => view.dispatch(tr));
    }
    view.focus();
  }

  function handleInsertPageBreak() {
    const view = opts.editorView.value;
    if (!view) return;
    insertPageBreak(view.state, (tr) => view.dispatch(tr), view);
    view.focus();
  }

  function handleInsertSectionBreakNextPage() {
    const view = opts.editorView.value;
    if (!view) return;
    insertSectionBreakNextPage(view.state, (tr) => view.dispatch(tr), view);
    view.focus();
  }

  function handleInsertSectionBreakContinuous() {
    const view = opts.editorView.value;
    if (!view) return;
    insertSectionBreakContinuous(view.state, (tr) => view.dispatch(tr), view);
    view.focus();
  }

  function handleInsertSymbol(symbol: string) {
    const view = targetView();
    if (!view) return;
    const { from } = view.state.selection;
    const tr = view.state.tr.insertText(symbol, from);
    view.dispatch(tr.scrollIntoView());
    view.focus();
  }

  function applyFormatting(options: ApplyFormattingOptions): boolean {
    const view = opts.editorView.value;
    if (!view) return false;
    return applyFormattingCore(view, options);
  }

  function setParagraphStyle(options: { paraId: string; styleId: string }): boolean {
    const view = opts.editorView.value;
    if (!view) return false;
    const doc = opts.getDocument();
    const styleResolver = doc?.package?.styles ? createStyleResolver(doc.package.styles) : null;
    const numbering = doc?.package?.numbering ? getCachedNumberingMap(doc.package.numbering) : null;
    return setParagraphStyleCore(view, options, { styleResolver, numbering });
  }

  function insertBreak(options: InsertBreakOptions): boolean {
    const view = opts.editorView.value;
    if (!view) return false;
    return insertBreakCore(view, options);
  }

  return {
    handleClearFormatting,
    handleApplyStyle,
    handleInsertPageBreak,
    handleInsertSectionBreakNextPage,
    handleInsertSectionBreakContinuous,
    handleInsertSymbol,
    applyFormatting,
    setParagraphStyle,
    insertBreak,
  };
}
