import { computed, nextTick, onBeforeUnmount, onMounted, ref } from "vue"
import { useRoute, useRouter } from "vue-router"

import editorApi from "@/module/editor/service/editor-api"
import { editorBridgeEventType } from "@/module/editor/model/editor-bridge-protocol"
import {
  buildSelectedSelectorSnapshot,
  buildSelectedElementSummary,
  buildQuickEditActions,
  buildRecommendedFlowSummary,
  buildSelectedPreviewSummary,
  buildCanvasCheckSummary,
  buildCanvasFeedbackSummary,
  buildPreviewFreshness,
  buildCanvasCandidates,
  buildDraftFormGuide,
  buildInteractionStateSummary,
  buildOperatorGuide,
  buildWorkspaceConsistency,
  buildInspectorSummary,
  buildWorkspaceJourney,
  buildWorkspaceNextAction,
  buildWorkspaceReadiness,
  createChangeDraft,
  editorChangeTemplates,
  formatChangesJson,
  mapEditorSession,
  mapPreviewOperations,
  normalizeDraftByType,
  parseChangesJson,
  summarizeChanges,
} from "@/module/editor/model/editor-workspace-model"

export function useEditorWorkspacePage() {
  const route = useRoute()
  const router = useRouter()
  const createEmptySelectedElementMeta = () => ({
    tag: "",
    text: "",
    href: "",
    src: "",
    hidden: false,
    source: "",
  })
  const variantId = computed(() => String(route.params.variantId || ""))
  const loading = ref(false)
  const errorMessage = ref("")
  const session = ref(null)
  const changes = ref([])
  const changesJson = ref("[]")
  const previewOperations = ref([])
  const baseUrl = ref("")
  const selectedSelector = ref("")
  const changeDraft = ref(createChangeDraft())
  const canvasBridgeState = ref("idle")
  const canvasBridgePageUrl = ref("")
  const selectedElementMeta = ref(createEmptySelectedElementMeta())
  const hoveredElementMeta = ref({
    selector: "",
    tag: "",
    text: "",
    href: "",
    src: "",
    source: "",
  })
  const canvasEventLog = ref([])
  const canvasBridgeCommand = ref(null)
  const canvasDocumentHtml = ref("")
  const draftFocusTarget = ref("")
  const deviceMode = ref("desktop")
  const historyStack = ref([])
  const historyIndex = ref(-1)
  const insertBlockType = ref("content-card")
  let liveEditHistoryTimer = null

  const insertBlockTypeOptions = [
    { value: "text-block", label: "文字區塊" },
    { value: "button-block", label: "按鈕區塊" },
    { value: "image-block", label: "圖片區塊" },
    { value: "content-card", label: "內容卡片" },
  ]
  const activeEditSelector = computed(() => selectedSelector.value)

  const snapshotEditorState = () => ({
    changesJson: changesJson.value,
    changeDraft: JSON.parse(JSON.stringify(changeDraft.value)),
    previewOperations: JSON.parse(JSON.stringify(previewOperations.value)),
    selectedSelector: selectedSelector.value,
    selectedElementMeta: JSON.parse(JSON.stringify(selectedElementMeta.value || createEmptySelectedElementMeta())),
    canvasDocumentHtml: canvasDocumentHtml.value,
  })

  const applySnapshot = (snapshot = {}) => {
    changesJson.value = snapshot.changesJson || "[]"
    changeDraft.value = normalizeDraftByType(snapshot.changeDraft || createChangeDraft())
    previewOperations.value = Array.isArray(snapshot.previewOperations) ? snapshot.previewOperations : []
    selectedSelector.value = snapshot.selectedSelector || ""
    selectedElementMeta.value = {
      ...createEmptySelectedElementMeta(),
      ...(snapshot.selectedElementMeta || {}),
    }
    canvasDocumentHtml.value = snapshot.canvasDocumentHtml || ""

    if (snapshot.canvasDocumentHtml) {
      canvasBridgeCommand.value = {
        type: editorBridgeEventType.RESTORE_CANVAS_STATE,
        pageHtml: snapshot.canvasDocumentHtml,
        selector: snapshot.selectedSelector || "",
        source: "editor-workspace",
        issuedAt: Date.now(),
      }

    }
  }

  const recordHistory = () => {
    const snapshot = snapshotEditorState()
    const nextStack = historyStack.value.slice(0, historyIndex.value + 1)
    const previousSnapshot = nextStack[nextStack.length - 1]

    if (previousSnapshot && JSON.stringify(previousSnapshot) === JSON.stringify(snapshot)) {
      return
    }

    nextStack.push(snapshot)
    historyStack.value = nextStack.slice(-20)
    historyIndex.value = historyStack.value.length - 1
  }

  const invalidatePreviewOperations = () => {
    if (!previewOperations.value.length) {
      return
    }

    previewOperations.value = []
  }

  const scheduleLiveEditHistory = () => {
    window.clearTimeout(liveEditHistoryTimer)
    liveEditHistoryTimer = window.setTimeout(() => {
      recordHistory()
    }, 280)
  }

  const canUndo = computed(() => historyIndex.value > 0)
  const canRedo = computed(() => historyIndex.value >= 0 && historyIndex.value < historyStack.value.length - 1)

  const previewOperationsPreview = computed(() =>
    JSON.stringify(previewOperations.value, null, 2)
  )
  const parsedChanges = computed(() => {
    try {
      return parseChangesJson(changesJson.value)
    } catch (error) {
      return []
    }
  })
  const changeSummary = computed(() => summarizeChanges(parsedChanges.value))
  const canvasCandidates = computed(() =>
    buildCanvasCandidates(parsedChanges.value)
  )
  const inspectorSummary = computed(() =>
    buildInspectorSummary({
      selectedSelector: selectedSelector.value,
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
    })
  )
  const interactionStateSummary = computed(() =>
    buildInteractionStateSummary({
      hoveredElementMeta: hoveredElementMeta.value,
      selectedSelector: selectedSelector.value,
      selectedElementMeta: selectedElementMeta.value,
    })
  )
  const workspaceConsistency = computed(() =>
    buildWorkspaceConsistency({
      selectedSelector: selectedSelector.value,
      draft: changeDraft.value,
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
    })
  )
  const selectedSelectorSnapshot = computed(() =>
    buildSelectedSelectorSnapshot({
      selectedSelector: selectedSelector.value,
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
    })
  )
  const selectedElementSummary = computed(() =>
    buildSelectedElementSummary({
      selectedSelector: selectedSelector.value,
      selectedElementMeta: selectedElementMeta.value,
    })
  )
  const quickEditActions = computed(() =>
    buildQuickEditActions({
      selectedSelector: selectedSelector.value,
      selectedElementSummary: selectedElementSummary.value,
      selectedElementMeta: selectedElementMeta.value,
    })
  )
  const draftFormGuide = computed(() =>
    buildDraftFormGuide({
      draft: changeDraft.value,
      selectedElementSummary: selectedElementSummary.value,
      selectedElementMeta: selectedElementMeta.value,
    })
  )
  const previewFreshness = computed(() =>
    buildPreviewFreshness({
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
      draft: changeDraft.value,
    })
  )
  const recommendedFlowSummary = computed(() =>
    buildRecommendedFlowSummary({
      selectedSelector: selectedSelector.value,
      selectedElementSummary: selectedElementSummary.value,
      draft: changeDraft.value,
      previewOperations: previewOperations.value,
    })
  )
  const selectedPreviewSummary = computed(() =>
    buildSelectedPreviewSummary({
      selectedSelector: selectedSelector.value,
      selectedSelectorSnapshot: selectedSelectorSnapshot.value,
    })
  )
  const canvasCheckSummary = computed(() =>
    buildCanvasCheckSummary({
      selectedSelector: selectedSelector.value,
      selectedElementSummary: selectedElementSummary.value,
      selectedPreviewSummary: selectedPreviewSummary.value,
    })
  )
  const canvasFeedbackSummary = computed(() =>
    buildCanvasFeedbackSummary({
      interactionStateSummary: interactionStateSummary.value,
      selectedSelector: selectedSelector.value,
      hoveredElementMeta: hoveredElementMeta.value,
      selectedElementSummary: selectedElementSummary.value,
      selectedPreviewSummary: selectedPreviewSummary.value,
      previewFreshness: previewFreshness.value,
    })
  )
  const workspaceReadiness = computed(() =>
    buildWorkspaceReadiness({
      baseUrl: baseUrl.value,
      session: session.value,
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
    })
  )
  const nextAction = computed(() =>
    buildWorkspaceNextAction({
      baseUrl: baseUrl.value,
      session: session.value,
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
    })
  )
  const workspaceJourney = computed(() =>
    buildWorkspaceJourney({
      baseUrl: baseUrl.value,
      session: session.value,
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
    })
  )
  const operatorGuide = computed(() =>
    buildOperatorGuide({
      baseUrl: baseUrl.value,
      session: session.value,
      selectedSelector: selectedSelector.value,
      draft: changeDraft.value,
      changes: parsedChanges.value,
      previewOperations: previewOperations.value,
    })
  )

  const applyTemplate = (templateKey) => {
    const template = editorChangeTemplates.find((item) => item.key === templateKey)
    if (!template) {
      return
    }

    changesJson.value = formatChangesJson([...parsedChanges.value, template.item])
    changeDraft.value = normalizeDraftByType({
      ...template.item,
      selector_value: selectedSelector.value || template.item.selector_value || "",
    })
  }

  const selectCanvasCandidate = (payload) => {
    const nextSelector =
      typeof payload === "string" ? payload : payload?.selector || ""

    selectedSelector.value = nextSelector
    changeDraft.value = normalizeDraftByType({
      ...changeDraft.value,
      selector_value: nextSelector,
    })
    selectedElementMeta.value = {
      tag: payload?.tag || "",
      text: payload?.text || "",
      href: payload?.href || "",
      src: payload?.src || "",
      hidden: Boolean(payload?.hidden),
      source: payload?.source || "candidate-button",
    }

    if (nextSelector) {
      canvasEventLog.value = [
        {
          id: `${Date.now()}-${nextSelector}`,
          type: "selection",
          value: nextSelector,
          source: payload?.source || "candidate-button",
        },
        ...canvasEventLog.value,
      ].slice(0, 8)
    }
  }

  const patchDraft = (patch = {}) => {
    changeDraft.value = normalizeDraftByType({
      ...changeDraft.value,
      ...patch,
      payload: {
        ...changeDraft.value.payload,
        ...(patch.payload || {}),
      },
    })
  }

  const setDeviceMode = (mode = "desktop") => {
    if (!["desktop", "tablet", "mobile"].includes(mode)) {
      return
    }
    deviceMode.value = mode
  }

  const moveSelectedBlock = (direction = "down") => {
    if (!selectedSelector.value || !["up", "down"].includes(direction)) {
      return
    }
    sendCanvasCommand(editorBridgeEventType.MOVE_BLOCK, selectedSelector.value, { direction })
  }

  const toggleSelectedBlockVisibility = () => {
    if (!selectedSelector.value) {
      return
    }
    sendCanvasCommand(editorBridgeEventType.TOGGLE_BLOCK_VISIBILITY, selectedSelector.value)
    selectedElementMeta.value = { ...selectedElementMeta.value, hidden: !selectedElementMeta.value.hidden }
  }

  const duplicateSelectedBlock = () => {
    if (!selectedSelector.value) {
      return
    }
    sendCanvasCommand(editorBridgeEventType.DUPLICATE_BLOCK, selectedSelector.value)
  }

  const deleteSelectedBlock = () => {
    if (!selectedSelector.value) {
      return
    }
    sendCanvasCommand(editorBridgeEventType.DELETE_BLOCK, selectedSelector.value)
  }

  const insertBlockNearSelection = (position = "after") => {
    if (!selectedSelector.value || !["before", "after"].includes(position)) {
      return
    }
    const selectedOption =
      insertBlockTypeOptions.find((option) => option.value === insertBlockType.value) ||
      insertBlockTypeOptions[insertBlockTypeOptions.length - 1]
    sendCanvasCommand(editorBridgeEventType.INSERT_BLOCK, selectedSelector.value, {
      position,
      blockType: selectedOption.value,
      blockTypeLabel: selectedOption.label,
    })
  }

  const applySelectedElementToDraft = () => {
    const targetSelector = activeEditSelector.value
    if (!targetSelector) {
      return
    }

    const textContent = selectedElementMeta.value.text || ""

    if (changeDraft.value.change_type === "replace_text" && textContent) {
      patchDraft({
        selector_value: targetSelector,
        payload: {
          text: textContent,
        },
      })
      return
    }

    if (changeDraft.value.change_type === "set_html" && textContent) {
      patchDraft({
        selector_value: targetSelector,
        payload: {
          html: textContent,
        },
      })
      return
    }

    patchDraft({
      selector_value: targetSelector,
    })
  }

  const applyRecommendedChangeType = () => {
    const targetSelector = activeEditSelector.value || selectedSelector.value
    const recommendedChangeType =
      selectedElementSummary.value?.recommendedChangeType || "replace_text"

    patchDraft({
      change_type: recommendedChangeType,
      selector_value: targetSelector,
      payload: {},
    })

    const textContent = selectedElementMeta.value.text || ""

    if (recommendedChangeType === "replace_text" && textContent) {
      patchDraft({
        payload: {
          text: textContent,
        },
      })
      return
    }

    if (recommendedChangeType === "set_html" && textContent) {
      patchDraft({
        payload: {
          html: textContent,
        },
      })
    }
  }

  const resolveDraftFocusTarget = (changeType = "", selectedMeta = {}, preferredField = "") => {
    if (preferredField) {
      return preferredField
    }

    if (changeType === "replace_text" || changeType === "set_html") {
      return "content"
    }

    if (changeType === "set_attribute") {
      if (selectedMeta?.src) {
        return "attribute-value"
      }

      return "attribute-name"
    }

    if (changeType === "set_style") {
      return "style-property"
    }

    return ""
  }

  const queueDraftFocus = async (target = "") => {
    if (!target) {
      return
    }

    draftFocusTarget.value = target
    await nextTick()
  }

  const clearDraftFocusTarget = () => {
    draftFocusTarget.value = ""
  }

  const startDraftEditFlow = async (intent = "") => {
    const targetSelector = activeEditSelector.value || selectedSelector.value
    if (!targetSelector) {
      return
    }

    if (!session.value?.id) {
      await createSession()

      if (!session.value?.id) {
        return
      }
    }

    loadSelectedSelectorIntoDraft()
    syncSelectedSelectorToDraft()

    const draftMatchesSelection =
      changeDraft.value?.selector_value === targetSelector

    const selectedMeta = selectedElementMeta.value || {}
    const forcedIntent =
      typeof intent === "string"
        ? {
            changeType: intent,
            focusTarget: "",
            attributeName: "",
            attributeValue: "",
          }
        : {
            changeType: intent?.changeType || "",
            focusTarget: intent?.focusTarget || "",
            attributeName: intent?.attributeName || "",
            attributeValue: intent?.attributeValue || "",
          }
    const targetChangeType =
      forcedIntent.changeType ||
      selectedElementSummary.value?.recommendedChangeType ||
      "replace_text"

    if (forcedIntent.changeType) {
      patchDraft({
        change_type: forcedIntent.changeType,
        selector_value: targetSelector,
        payload: {},
      })

      if (forcedIntent.changeType === "replace_text") {
        patchDraft({
          payload: {
            text: selectedMeta.text || "新的主標題文案",
          },
        })
      } else if (forcedIntent.changeType === "set_attribute") {
        patchDraft({
          payload: {
            name:
              forcedIntent.attributeName ||
              (selectedMeta.src ? "src" : selectedMeta.href ? "href" : "href"),
            value:
              forcedIntent.attributeValue ||
              selectedMeta.src ||
              selectedMeta.href ||
              "https://ose.tw",
          },
        })
      } else if (forcedIntent.changeType === "set_style") {
        patchDraft({
          payload: {
            property: "backgroundColor",
            value: "#111827",
          },
        })
      } else {
        applyRecommendedChangeType()
      }
    } else if (
      !draftMatchesSelection ||
      !changeDraft.value?.change_type ||
      !changeDraft.value?.payload ||
      Object.keys(changeDraft.value.payload || {}).length === 0
    ) {
      applyRecommendedChangeType()
    }

    scrollToSection("editor-draft-section")
    await queueDraftFocus(
      resolveDraftFocusTarget(targetChangeType, selectedMeta, forcedIntent.focusTarget)
    )

    if (targetChangeType === "replace_text") {
      sendCanvasCommand("mkt-editor:start-inline-edit", targetSelector, {
        editKind: "replace_text",
      })
    }

    if (targetChangeType === "set_attribute") {
      sendCanvasCommand("mkt-editor:start-inline-edit", targetSelector, {
        editKind: "set_attribute",
        attributeName:
          forcedIntent.attributeName ||
          changeDraft.value?.payload?.name ||
          (selectedMeta.src ? "src" : "href"),
        attributeValue:
          forcedIntent.attributeValue ||
          changeDraft.value?.payload?.value ||
          selectedMeta.src ||
          selectedMeta.href ||
          "",
      })
    }

    if (targetChangeType === "set_style") {
      sendCanvasCommand("mkt-editor:start-inline-edit", targetSelector, {
        editKind: "set_style",
        styleProperty: changeDraft.value?.payload?.property || "backgroundColor",
        styleValue: changeDraft.value?.payload?.value || "#111827",
      })
    }
  }

  const runRecommendedFlow = async () => {
    if (!selectedSelector.value) {
      return
    }

    const draftMatchesSelection =
      changeDraft.value?.selector_value === selectedSelector.value

    if (!draftMatchesSelection) {
      applyRecommendedChangeType()
      return
    }

    await buildPreview()
  }

  const runSelectedPreviewFlow = async () => {
    if (!selectedSelector.value) {
      return
    }

    if ((selectedSelectorSnapshot.value?.previewOperations || []).length === 0) {
      await buildPreview()
      return
    }

    scrollToSection("editor-canvas-section")
  }

  const runCanvasCheckFlow = async () => {
    if (!selectedSelector.value) {
      return
    }

    if (selectedPreviewSummary.value.status !== "ready") {
      await runSelectedPreviewFlow()
      return
    }

    focusSelectedOnCanvas()
    scrollToSection("editor-canvas-section")
  }

  const runQuickEditAction = async (changeType = "") => {
    if (!changeType) {
      return
    }

    await startDraftEditFlow({
      changeType,
      focusTarget: resolveDraftFocusTarget(changeType, selectedElementMeta.value || {}),
    })
  }

  const syncSelectedSelectorToDraft = () => {
    const targetSelector = activeEditSelector.value || selectedSelector.value
    if (!targetSelector) {
      return
    }

    patchDraft({
      selector_value: targetSelector,
    })
  }

  const applyDraftToChanges = () => {
    const nextDraft = normalizeDraftByType(changeDraft.value)
    changesJson.value = formatChangesJson([...parsedChanges.value, nextDraft])
    recordHistory()
  }

  const replaceChangesWithDraft = () => {
    const nextDraft = normalizeDraftByType(changeDraft.value)
    changesJson.value = formatChangesJson([nextDraft])
    recordHistory()
  }

  const loadSelectedSelectorIntoDraft = () => {
    const targetSelector = activeEditSelector.value || selectedSelector.value
    if (!targetSelector) {
      return
    }

    const matchedChange = parsedChanges.value.find(
      (item) => item.selector_value === targetSelector
    )

    if (matchedChange) {
      changeDraft.value = normalizeDraftByType(matchedChange)
      return
    }

    changeDraft.value = normalizeDraftByType({
      ...changeDraft.value,
      selector_value: targetSelector,
    })
  }

  const createSession = async () => {
    loading.value = true
    errorMessage.value = ""

    try {
      const response = await editorApi.createEditorSession({
        variant_id: variantId.value,
        base_url: baseUrl.value || null,
        mode: "edit",
      })
      session.value = mapEditorSession(response)
    } catch (error) {
      errorMessage.value = error?.message || "無法建立 editor session。"
    } finally {
      loading.value = false
    }
  }

  const loadChanges = async () => {
    loading.value = true
    errorMessage.value = ""

    try {
      changes.value = await editorApi.getVariantChanges(variantId.value)
      changesJson.value = formatChangesJson(changes.value)
      recordHistory()
    } catch (error) {
      errorMessage.value = error?.message || "無法載入 variant changes。"
    } finally {
      loading.value = false
    }
  }

  const saveChanges = async () => {
    loading.value = true
    errorMessage.value = ""

    try {
      const items = parseChangesJson(changesJson.value)
      changes.value = await editorApi.saveVariantChanges(variantId.value, items)
      changesJson.value = formatChangesJson(changes.value)
    } catch (error) {
      errorMessage.value = error?.message || "無法保存 variant changes。"
    } finally {
      loading.value = false
    }
  }

  const buildPreview = async () => {
    loading.value = true
    errorMessage.value = ""

    try {
      const items = parseChangesJson(changesJson.value)
      const preview = await editorApi.buildPreview({
        variant_id: variantId.value,
        items: items,
      })
      previewOperations.value = mapPreviewOperations(preview)
      recordHistory()
    } catch (error) {
      errorMessage.value = error?.message || "無法 build preview。"
    } finally {
      loading.value = false
    }
  }

  const undoHistory = () => {
    if (!canUndo.value) {
      return
    }

    historyIndex.value -= 1
    applySnapshot(historyStack.value[historyIndex.value])
  }

  const redoHistory = () => {
    if (!canRedo.value) {
      return
    }

    historyIndex.value += 1
    applySnapshot(historyStack.value[historyIndex.value])
  }

  const goBack = () => {
    router.back()
  }

  const loadDemoPage = () => {
    if (typeof window === "undefined") {
      return
    }

    baseUrl.value = `${window.location.origin}/editor-demo.html`
  }

  const handleCanvasReady = (payload = {}) => {
    canvasBridgeState.value = "ready"
    canvasBridgePageUrl.value = payload.page_url || baseUrl.value || ""
    if (payload.page_html) {
      const shouldSeedHistory =
        !canvasDocumentHtml.value ||
        historyStack.value.length === 0 ||
        !historyStack.value[historyStack.value.length - 1]?.canvasDocumentHtml

      canvasDocumentHtml.value = payload.page_html

      if (shouldSeedHistory) {
        recordHistory()
      }
    }
    canvasEventLog.value = [
      {
        id: `${Date.now()}-ready`,
        type: "ready",
        value: payload.page_url || baseUrl.value || "",
        source: "canvas-bridge",
      },
      ...canvasEventLog.value,
    ].slice(0, 8)
  }

  const applySelectedMetaFromPayload = (payload = {}, fallbackMeta = selectedElementMeta.value) => ({
    ...fallbackMeta,
    tag: payload.tag || fallbackMeta.tag || "",
    text: payload.text || fallbackMeta.text || "",
    href: payload.href || fallbackMeta.href || "",
    src: payload.src || fallbackMeta.src || "",
    hidden: Boolean(payload.hidden),
    source: payload.source || "canvas-bridge",
  })

  const syncDraftSelectorAfterStructureChange = (previousSelectedSelector = "", nextSelector = "") => {
    if (
      changeDraft.value?.selector_value &&
      changeDraft.value.selector_value === previousSelectedSelector
    ) {
      patchDraft({
        selector_value: nextSelector || "",
      })
    }

    if (!nextSelector) {
      changeDraft.value = normalizeDraftByType({
        ...changeDraft.value,
        selector_value: "",
      })
      clearDraftFocusTarget()
    }
  }

  const handleCanvasOutbound = (payload = {}) => {
    if (!payload?.type) {
      return
    }

    if (
      payload.type === editorBridgeEventType.BLOCK_VISIBILITY_CHANGE &&
      payload.selector === selectedSelector.value
    ) {
      selectedElementMeta.value = applySelectedMetaFromPayload(payload)
      canvasDocumentHtml.value = payload.pageHtml || canvasDocumentHtml.value
      invalidatePreviewOperations()
      recordHistory()
    }

    if (payload.type === editorBridgeEventType.BLOCK_STRUCTURE_CHANGE) {
      const previousSelectedSelector = selectedSelector.value
      canvasDocumentHtml.value = payload.pageHtml || canvasDocumentHtml.value
      invalidatePreviewOperations()
      if (["move", "duplicate"].includes(payload.action) && payload.nextSelector) {
        selectedSelector.value = payload.nextSelector
        selectedElementMeta.value = applySelectedMetaFromPayload(payload)
      }

      if (payload.action === "delete") {
        selectedSelector.value = payload.nextSelector || ""
        if (!payload.nextSelector) {
          selectedElementMeta.value = createEmptySelectedElementMeta()
        } else {
          selectedElementMeta.value = applySelectedMetaFromPayload(payload)
        }
      }

      if (payload.action === "insert" && payload.nextSelector) {
        selectedSelector.value = payload.nextSelector
        selectedElementMeta.value = applySelectedMetaFromPayload(payload)

        if (payload.blockType === "button-block") {
          patchDraft({
            change_type: "set_attribute",
            selector_value: payload.nextSelector,
            payload: {
              name: "href",
              value: payload.href || "https://ose.tw",
            },
          })
          draftFocusTarget.value = "attribute-value"
          sendCanvasCommand(editorBridgeEventType.START_INLINE_EDIT, payload.nextSelector, {
            editKind: "set_attribute",
            attributeName: "href",
            attributeValue: payload.href || "https://ose.tw",
          })
        } else if (payload.blockType === "image-block") {
          patchDraft({
            change_type: "set_attribute",
            selector_value: payload.nextSelector,
            payload: {
              name: "src",
              value: payload.src || "",
            },
          })
          draftFocusTarget.value = "attribute-value"
          sendCanvasCommand(editorBridgeEventType.START_INLINE_EDIT, payload.nextSelector, {
            editKind: "set_attribute",
            attributeName: "src",
            attributeValue: payload.src || "",
          })
        } else {
          patchDraft({
            change_type: "replace_text",
            selector_value: payload.nextSelector,
            payload: {
              text: payload.text || "新的區塊標題",
            },
          })
          draftFocusTarget.value = "content"
          if (payload.blockType === "text-block") {
            sendCanvasCommand(editorBridgeEventType.START_INLINE_EDIT, payload.nextSelector, {
              editKind: "replace_text",
            })
          }
        }
      }

      syncDraftSelectorAfterStructureChange(previousSelectedSelector, payload.nextSelector || "")
      recordHistory()
    }

    canvasEventLog.value = [
      {
        id: `${Date.now()}-${payload.type}`,
        type: payload.type,
        value: payload.value || "",
        source: payload.source || "editor-workspace",
      },
      ...canvasEventLog.value,
    ].slice(0, 8)
  }

  const hydrateSelectionFromPayload = (payload = {}) => {
    if (payload.selector) {
      selectedSelector.value = payload.selector
    }

    selectedElementMeta.value = {
      tag: payload.tag || selectedElementMeta.value.tag || "",
      text: payload.text || selectedElementMeta.value.text || "",
      href: payload.href || selectedElementMeta.value.href || "",
      src: payload.src || selectedElementMeta.value.src || "",
      hidden: Boolean(payload.hidden),
      source: payload.source || selectedElementMeta.value.source || "canvas-hotspot",
    }
  }

  const hydrateDraftIntentFromPayload = (payload = {}) => {
    if (!payload.intentChangeType) {
      return
    }

    patchDraft({
      change_type: payload.intentChangeType,
      selector_value: payload.selector || selectedSelector.value,
      payload:
        payload.intentChangeType === "set_attribute"
          ? {
              name: payload.intentAttributeName || "href",
              value: payload.intentAttributeValue || "",
            }
          : payload.intentChangeType === "set_style"
          ? {
              property: "backgroundColor",
              value: "#111827",
            }
          : payload.intentChangeType === "replace_text"
          ? {
              text: payload.text || selectedElementMeta.value.text || "新的主標題文案",
            }
          : {},
    })
  }

  const handleCanvasHotspotAction = async (payload = {}) => {
    hydrateSelectionFromPayload(payload)
    hydrateDraftIntentFromPayload(payload)

    switch (payload.action) {
      case "select-current":
        loadSelectedSelectorIntoDraft()
        syncSelectedSelectorToDraft()
        scrollToSection("editor-inspector-section")
        return
      case "inspect-current":
        scrollToSection("editor-inspector-section")
        return
      case "edit-current":
        await startDraftEditFlow()
        return
      case "edit-text-current":
        await startDraftEditFlow({
          changeType: payload.intentChangeType || "replace_text",
          focusTarget: payload.intentField || "content",
        })
        return
      case "edit-link-current":
      case "edit-image-current":
        await startDraftEditFlow({
          changeType: payload.intentChangeType || "set_attribute",
          focusTarget: payload.intentField || "attribute-value",
          attributeName: payload.intentAttributeName || "",
          attributeValue: payload.intentAttributeValue || "",
        })
        return
      case "edit-style-current":
        await startDraftEditFlow({
          changeType: payload.intentChangeType || "set_style",
          focusTarget: payload.intentField || "style-property",
        })
        return
      case "confirm-current":
        await runCanvasCheckFlow()
        return
      default:
        return
    }
  }

  const handleCanvasHover = (payload = {}) => {
    hoveredElementMeta.value = {
      selector: payload.selector || "",
      tag: payload.tag || "",
      text: payload.text || "",
      href: payload.href || "",
      src: payload.src || "",
      source: payload.source || "canvas-hover",
    }
  }

  const handleInlineTextChange = (payload = {}) => {
    if (!payload.selector) {
      return
    }

    selectedSelector.value = payload.selector
    selectedElementMeta.value = {
      ...selectedElementMeta.value,
      text: payload.text || selectedElementMeta.value.text || "",
      source: payload.source || "canvas-inline-edit",
    }
    canvasDocumentHtml.value = payload.pageHtml || canvasDocumentHtml.value
    invalidatePreviewOperations()

    if (changeDraft.value.change_type === "replace_text") {
      patchDraft({
        selector_value: payload.selector,
        payload: {
          text: payload.text || "",
        },
      })
    }

    if (payload.source === "canvas-inline-edit-live") {
      scheduleLiveEditHistory()
    } else {
      recordHistory()
    }
  }

  const clearHoveredCandidate = () => {
    hoveredElementMeta.value = {
      selector: "",
      tag: "",
      text: "",
      href: "",
      src: "",
      hidden: false,
      source: "",
    }
  }

  const keepCurrentSelection = () => {
    clearHoveredCandidate()
    focusSelectedOnCanvas()
    scrollToSection("editor-canvas-section")
  }

  const promoteHoveredToSelected = () => {
    if (!hoveredElementMeta.value.selector) {
      return
    }

    selectCanvasCandidate({
      selector: hoveredElementMeta.value.selector,
      tag: hoveredElementMeta.value.tag,
      text: hoveredElementMeta.value.text,
      href: hoveredElementMeta.value.href,
      src: hoveredElementMeta.value.src,
      source: "canvas-hover-promoted",
    })
    clearHoveredCandidate()
  }

  const inspectHoveredOnCanvas = () => {
    if (!hoveredElementMeta.value.selector) {
      return
    }

    sendCanvasCommand("mkt-editor:inspect-selector", hoveredElementMeta.value.selector)
    scrollToSection("editor-canvas-section")
  }

  const sendCanvasCommand = (type, selector, extra = {}) => {
    if (!selector) {
      return
    }

    canvasBridgeCommand.value = {
      id: `${Date.now()}-${type}-${selector}`,
      type,
      selector,
      ...extra,
      source: "editor-workspace",
    }
  }

  const handleInlineAttributeChange = (payload = {}) => {
    if (!payload.selector || !payload.attributeName) {
      return
    }

    selectedSelector.value = payload.selector
    selectedElementMeta.value = {
      ...selectedElementMeta.value,
      href:
        payload.attributeName === "href"
          ? payload.attributeValue || ""
          : selectedElementMeta.value.href || "",
      src:
        payload.attributeName === "src"
          ? payload.attributeValue || ""
          : selectedElementMeta.value.src || "",
      source: payload.source || "canvas-inline-edit",
    }
    canvasDocumentHtml.value = payload.pageHtml || canvasDocumentHtml.value
    invalidatePreviewOperations()

    if (changeDraft.value.change_type === "set_attribute") {
      patchDraft({
        selector_value: payload.selector,
        payload: {
          name: payload.attributeName,
          value: payload.attributeValue || "",
        },
      })
    }

    if (payload.source === "canvas-inline-edit-live") {
      scheduleLiveEditHistory()
    } else {
      recordHistory()
    }
  }

  const handleInlineStyleChange = (payload = {}) => {
    if (!payload.selector || !payload.styleProperty) {
      return
    }

    selectedSelector.value = payload.selector
    selectedElementMeta.value = {
      ...selectedElementMeta.value,
      source: payload.source || "canvas-inline-edit",
    }
    canvasDocumentHtml.value = payload.pageHtml || canvasDocumentHtml.value
    invalidatePreviewOperations()

    if (changeDraft.value.change_type === "set_style") {
      patchDraft({
        selector_value: payload.selector,
        payload: {
          property: payload.styleProperty,
          value: payload.styleValue || "",
        },
      })
    }

    if (payload.source === "canvas-inline-edit-live") {
      scheduleLiveEditHistory()
    } else {
      recordHistory()
    }
  }

  const focusSelectedOnCanvas = () => {
    sendCanvasCommand("mkt-editor:focus-selector", selectedSelector.value)
  }

  const inspectSelectedOnCanvas = () => {
    sendCanvasCommand("mkt-editor:inspect-selector", selectedSelector.value)
  }

  const runInteractionStateAction = async () => {
    switch (interactionStateSummary.value.stage) {
      case "idle":
        scrollToSection("editor-canvas-section")
        return
      case "hover":
        promoteHoveredToSelected()
        return
      case "compare":
        keepCurrentSelection()
        return
      default:
        await runCanvasCheckFlow()
    }
  }

  const scrollToSection = (sectionId) => {
    document
      .getElementById(sectionId)
      ?.scrollIntoView({ behavior: "smooth", block: "start" })
  }

  const runNextAction = async () => {
    switch (nextAction.value.key) {
      case "create_session":
        await createSession()
        return
      case "apply_template":
        applyTemplate("replace_text")
        return
      case "build_preview":
        await buildPreview()
        return
      case "canvas_next":
        scrollToSection("editor-canvas-section")
        return
      default:
        return
    }
  }

  onMounted(async () => {
    if (typeof route.query.base_url === "string" && route.query.base_url) {
      baseUrl.value = route.query.base_url
    }
    await loadChanges()
    if (canvasCandidates.value.length > 0) {
      selectCanvasCandidate({
        ...canvasCandidates.value[0],
        source: "initial-candidate",
      })
      changeDraft.value = normalizeDraftByType({
        ...changeDraft.value,
        selector_value: selectedSelector.value,
      })
    }
    if (historyStack.value.length === 0) {
      recordHistory()
    }
  })

  onBeforeUnmount(() => {
    window.clearTimeout(liveEditHistoryTimer)
  })

  return {
    variantId,
    loading,
    errorMessage,
    session,
    changes,
    changesJson,
    previewOperations,
    previewOperationsPreview,
    parsedChanges,
    changeSummary,
    canvasCandidates,
    interactionStateSummary,
    inspectorSummary,
    workspaceConsistency,
    selectedSelectorSnapshot,
    selectedElementSummary,
    quickEditActions,
    previewFreshness,
    recommendedFlowSummary,
    selectedPreviewSummary,
    canvasCheckSummary,
    canvasFeedbackSummary,
    selectedSelector,
    changeDraft,
    canvasBridgeState,
    canvasBridgePageUrl,
    selectedElementMeta,
    hoveredElementMeta,
    canvasEventLog,
    canvasBridgeCommand,
    workspaceReadiness,
    nextAction,
    workspaceJourney,
    operatorGuide,
    draftFormGuide,
    changeTemplates: editorChangeTemplates,
    baseUrl,
    selectCanvasCandidate,
    patchDraft,
    applySelectedElementToDraft,
    applyRecommendedChangeType,
    runRecommendedFlow,
    runSelectedPreviewFlow,
    runCanvasCheckFlow,
    runQuickEditAction,
    startDraftEditFlow,
    syncSelectedSelectorToDraft,
    applyDraftToChanges,
    replaceChangesWithDraft,
    loadSelectedSelectorIntoDraft,
    applyTemplate,
    createSession,
    loadChanges,
    saveChanges,
    buildPreview,
    loadDemoPage,
    runNextAction,
    scrollToSection,
    handleCanvasReady,
    handleCanvasHotspotAction,
    handleCanvasHover,
    handleInlineAttributeChange,
    handleInlineStyleChange,
    handleInlineTextChange,
    clearHoveredCandidate,
    keepCurrentSelection,
    handleCanvasOutbound,
    promoteHoveredToSelected,
    inspectHoveredOnCanvas,
    focusSelectedOnCanvas,
    inspectSelectedOnCanvas,
    runInteractionStateAction,
    draftFocusTarget,
    clearDraftFocusTarget,
    goBack,
    deviceMode,
    setDeviceMode,
    insertBlockType,
    insertBlockTypeOptions,
    moveSelectedBlock,
    toggleSelectedBlockVisibility,
    duplicateSelectedBlock,
    deleteSelectedBlock,
    insertBlockNearSelection,
    canUndo,
    canRedo,
    undoHistory,
    redoHistory,
  }
}
