"use client"

import { useEditorState } from "@tiptap/react"
import type { Editor } from "@tiptap/react"
import {
  canStepFontSizePx,
  readFontSizeToolbarState,
  type FontSizeToolbarState,
} from "@/lib/drive/docs-font-size"
import {
  readFontFamilyToolbarState,
  type FontFamilyToolbarState,
} from "@/lib/drive/docs-font-family"
import { readActiveParagraphStyleId } from "@/lib/drive/docs-paragraph-style-apply"
import {
  canDecreaseDocsIndent,
  canIncreaseDocsIndent,
} from "@/lib/drive/docs-indent-actions"
import { readDocsParagraphSpacingState } from "@/lib/drive/docs-line-spacing-actions"
import { readDocsListState } from "@/lib/drive/docs-list-actions"

export const DOCS_TOOLBAR_DEFAULT_TEXT_COLOR = "#000000"

export type DocsToolbarEditorState = {
  canUndo: boolean
  canRedo: boolean
  styleId: string
  fontFamilyState: FontFamilyToolbarState
  fontSizeState: FontSizeToolbarState
  canStepFontSizeDown: boolean
  canStepFontSizeUp: boolean
  textColor: string
  highlightColor: string | null
  isBold: boolean
  isItalic: boolean
  isUnderline: boolean
  isLink: boolean
  alignLeft: boolean
  alignCenter: boolean
  alignRight: boolean
  alignJustify: boolean
  isBulletList: boolean
  isOrderedList: boolean
  isTaskList: boolean
  canIncreaseIndent: boolean
  canDecreaseIndent: boolean
  lineHeightPresetId: string | "mixed" | null
  graphicSelected: boolean
}

function readHighlightColor(editor: Editor): string | null {
  const { storedMarks } = editor.state
  if (storedMarks) {
    const mark = storedMarks.find((m) => m.type.name === "highlight")
    const stored = mark?.attrs.color as string | undefined
    if (stored) return stored
  }

  if (!editor.isActive("highlight")) return null
  const color = editor.getAttributes("highlight").color as string | undefined
  return color ?? null
}

function selectDocsToolbarState({ editor }: { editor: Editor }): DocsToolbarEditorState {
  const highlightColor = readHighlightColor(editor)
  const spacing = readDocsParagraphSpacingState(editor)
  const listState = readDocsListState(editor)

  return {
    canUndo: editor.can().chain().focus().undo().run(),
    canRedo: editor.can().chain().focus().redo().run(),
    styleId: readActiveParagraphStyleId(editor),
    fontFamilyState: readFontFamilyToolbarState(editor),
    fontSizeState: readFontSizeToolbarState(editor),
    canStepFontSizeDown: canStepFontSizePx(editor, -1),
    canStepFontSizeUp: canStepFontSizePx(editor, 1),
    textColor:
      (editor.getAttributes("textStyle").color as string | undefined) ||
      DOCS_TOOLBAR_DEFAULT_TEXT_COLOR,
    highlightColor,
    isBold: editor.isActive("bold"),
    isItalic: editor.isActive("italic"),
    isUnderline: editor.isActive("underline"),
    isLink: editor.isActive("link"),
    alignLeft: editor.isActive({ textAlign: "left" }),
    alignCenter: editor.isActive({ textAlign: "center" }),
    alignRight: editor.isActive({ textAlign: "right" }),
    alignJustify: editor.isActive({ textAlign: "justify" }),
    isBulletList: editor.isActive("bulletList"),
    isOrderedList: editor.isActive("orderedList"),
    isTaskList: listState.isTaskList,
    canIncreaseIndent: canIncreaseDocsIndent(editor),
    canDecreaseIndent: canDecreaseDocsIndent(editor),
    lineHeightPresetId: spacing.lineHeightPresetId,
    graphicSelected:
      editor.isActive("docsGraphic") || editor.isActive("docsInlineGraphic"),
  }
}

function fontFamilyStateEqual(a: FontFamilyToolbarState, b: FontFamilyToolbarState): boolean {
  if (a.kind !== b.kind) return false
  if (a.kind === "single" && b.kind === "single") return a.name === b.name
  return true
}

function fontSizeStateEqual(a: FontSizeToolbarState, b: FontSizeToolbarState): boolean {
  if (a.kind !== b.kind) return false
  if (a.kind === "single" && b.kind === "single") return a.size === b.size
  return true
}

function toolbarStateEqual(
  a: DocsToolbarEditorState,
  b: DocsToolbarEditorState | null
): boolean {
  if (!b) return false
  if (!fontFamilyStateEqual(a.fontFamilyState, b.fontFamilyState)) return false
  if (!fontSizeStateEqual(a.fontSizeState, b.fontSizeState)) return false

  return (
    a.canUndo === b.canUndo &&
    a.canRedo === b.canRedo &&
    a.styleId === b.styleId &&
    a.canStepFontSizeDown === b.canStepFontSizeDown &&
    a.canStepFontSizeUp === b.canStepFontSizeUp &&
    a.textColor === b.textColor &&
    a.highlightColor === b.highlightColor &&
    a.isBold === b.isBold &&
    a.isItalic === b.isItalic &&
    a.isUnderline === b.isUnderline &&
    a.isLink === b.isLink &&
    a.alignLeft === b.alignLeft &&
    a.alignCenter === b.alignCenter &&
    a.alignRight === b.alignRight &&
    a.alignJustify === b.alignJustify &&
    a.isBulletList === b.isBulletList &&
    a.isOrderedList === b.isOrderedList &&
    a.isTaskList === b.isTaskList &&
    a.canIncreaseIndent === b.canIncreaseIndent &&
    a.canDecreaseIndent === b.canDecreaseIndent &&
    a.lineHeightPresetId === b.lineHeightPresetId &&
    a.graphicSelected === b.graphicSelected
  )
}

function selectDocsToolbarStateOptional({
  editor,
}: {
  editor: Editor | null
}): DocsToolbarEditorState | null {
  if (!editor) return null
  return selectDocsToolbarState({ editor })
}

function toolbarStateEqualOptional(
  a: DocsToolbarEditorState | null,
  b: DocsToolbarEditorState | null
): boolean {
  if (a == null || b == null) return a === b
  return toolbarStateEqual(a, b)
}

export function useDocsToolbarState(editor: Editor | null): DocsToolbarEditorState | null {
  return useEditorState({
    editor,
    selector: selectDocsToolbarStateOptional,
    equalityFn: toolbarStateEqualOptional,
  })
}
