import { useMemo, useState } from "react"
import { toast } from "sonner"

import { CancelStatusIcon, CheckCircleStatusIcon, LoaderRefreshIcon } from "@/components/icons"
import { useConvertToMindMap } from "@/features/board/api/convert-to-mindmap"
import { useDrawify } from "@/features/board/api/drawify"
import { useTranslateText } from "@/features/board/api/translate-text"
import { useMindMapStore } from "@/features/agent/store/mindmap-store"
import { createDefaultLinkStyle, createDefaultStyle } from "@/features/board/types/style"
import { convertLinkToEdge, convertNoteToNode } from "@/features/board/utils/graph"
import { autoLayout } from "@/features/board/lib/graph/auto-layout"
import { defaultLayoutOptions } from "@/features/board/lib/graph/settings"
import { pickRandomColorOfShade } from "@/features/board/lib/colors/tailwind"
import type { LinkEdge, NoteNode } from "@/features/board/types/flow"
import type { Note } from "@/features/board/types/note"
import type { Link } from "@/features/board/types/link"

export type AiSparkAction = {
  key: string
  label: string
  request: string
}

export type AiSparkRunParams = {
  boardId?: string
  contextText: string
  actionKey?: string
  customRequest?: string
  useAnchors?: boolean
  targetLanguage?: string
}

const defaultActions: AiSparkAction[] = [
  { key: "summarize", label: "Write a summary", request: "Write a concise summary." },
  { key: "mapify", label: "Mapify (generate mindmap)", request: "Generate a mindmap capturing the main ideas and relationships." },
  { key: "schemify", label: "Schemify (generate schema)", request: "Generate a structured schema of entities and relationships." },
  { key: "quizify", label: "Quizify (MCQ exercises)", request: "Generate multiple-choice exercises grouped by theme." },
  { key: "drawify", label: "Draw (beta)", request: "Draw a clean diagram with clear layout and spacing." },
  { key: "translate", label: "Translate", request: "Translate the input to the target language." },
  { key: "explain", label: "Explain (more detail)", request: "Explain the content in more detail with clear, step-by-step reasoning." },
]

export const useAiSparkActions = () => {
  const { convertToMindMapAsync } = useConvertToMindMap()
  const { drawifyAsync } = useDrawify()
  const { translateTextAsync } = useTranslateText()
  const setMindMap = useMindMapStore(state => state.setMindMap)
  const [processingKey, setProcessingKey] = useState<string | null>(null)

  const actions = useMemo(() => defaultActions, [])

  const storeMindMap = async ({
    boardId,
    notes,
    links,
    useAnchors,
    preserveStyle = false,
    layout = true,
  }: {
    boardId: string
    notes: Note[]
    links: Link[]
    useAnchors?: boolean
    preserveStyle?: boolean
    layout?: boolean
  }) => {
    notes.forEach(note => {
      note.graphUid = boardId
      note.style = preserveStyle
        ? { ...createDefaultStyle({ type: note.style.type }), ...note.style }
        : createDefaultStyle({ type: note.style.type })
    })
    links.forEach(link => {
      link.graphUid = boardId
      link.style = preserveStyle
        ? { ...createDefaultLinkStyle(), ...link.style }
        : createDefaultLinkStyle()
    })
    if (notes.length > 0) {
      if (!preserveStyle) {
        notes.forEach((note) => {
          note.style.backgroundColor = pickRandomColorOfShade(200, undefined)?.hex || note.style.backgroundColor
        })
      }
    }

    notes.forEach((note, index) => {
      const z = note.properties?.nodeZIndex?.number
      if (z === undefined || z === null) {
        note.properties.nodeZIndex.number = index
      }
    })

    const rawNodes = notes.map(convertNoteToNode)
    const rawEdges = links.map(convertLinkToEdge)
    const ns: NoteNode[] = []
    const es: LinkEdge[] = []

    const baseNodes = layout
      ? (await autoLayout(rawNodes, rawEdges, defaultLayoutOptions)).nodes
      : rawNodes
    ns.push(...baseNodes)
    es.push(...rawEdges)

    setMindMap(boardId, ns, es, useAnchors)
  }

  const runAction = async ({
    boardId,
    contextText,
    actionKey,
    customRequest,
    useAnchors = true,
    targetLanguage = "English",
  }: AiSparkRunParams) => {
    if (!boardId) {
      toast.error("Select a board first.")
      return false
    }
    if (!contextText.trim()) {
      toast.error("Add some context text first.")
      return false
    }
    if (processingKey) return false

    const action = actionKey ? actions.find((item) => item.key === actionKey) : undefined
    const request = (customRequest ?? action?.request ?? "").trim()

    if (!request && actionKey !== "translate") {
      toast.error("Add a request first.")
      return false
    }

    setProcessingKey(actionKey ?? "custom")
    const startedAt = Date.now()
    const formatElapsed = () => `${Math.max(0, Math.floor((Date.now() - startedAt) / 1000))}s`
    const toastId = toast(`Working on it… ${formatElapsed()}`, {
      duration: Infinity,
      icon: <LoaderRefreshIcon className="size-4 animate-spin [animation-duration:750ms]" />,
    })
    const timer = window.setInterval(() => {
      toast(`Working on it… ${formatElapsed()}`, {
        id: toastId,
        icon: <LoaderRefreshIcon className="size-4 animate-spin [animation-duration:750ms]" />,
      })
    }, 1000)
    try {
      if (actionKey === "translate") {
        const { notes, links } = await translateTextAsync({
          text: contextText.trim(),
          targetLanguage
        })
        await storeMindMap({ boardId, notes, links, useAnchors })
      } else if (actionKey === "drawify") {
        const answer = `Request: ${request}\n---\nInput Text:\n${contextText.trim()}`
        const { notes, links } = await drawifyAsync({ answer })
        await storeMindMap({ boardId, notes, links, useAnchors, preserveStyle: true, layout: false })
      } else {
        const answer = `Request: ${request}\n---\nInput Text:\n${contextText.trim()}`
        const toolType = actionKey === "mapify"
          ? "mapify"
          : actionKey === "schemify"
            ? "schemify"
            : actionKey === "quizify"
              ? "quizify"
              : "summify"
        await convertToMindMapAsync({ boardId, answer, toolType, useAnchors })
      }
      window.clearInterval(timer)
      toast.dismiss(toastId)
      const finalElapsed = formatElapsed()
      toast.success(`Added to board. (${finalElapsed})`, {
        icon: <CheckCircleStatusIcon className="size-4" />,
        duration: 3000,
      })
      return true
    } catch (error) {
      console.error("AI action failed:", error)
      window.clearInterval(timer)
      toast.dismiss(toastId)
      const finalElapsed = formatElapsed()
      toast.error(`Could not complete the action. (${finalElapsed})`, {
        icon: <CancelStatusIcon className="size-4" />,
        duration: 4000,
      })
      return false
    } finally {
      window.clearInterval(timer)
      setProcessingKey(null)
    }
  }

  return {
    actions,
    processingKey,
    runAction,
  }
}
