<template>
  <div class="workspace">
    <div class="workspace-header">
      <div></div>
      <div class="header-actions">
        <template v-if="isEditMode">
          <n-dropdown trigger="click" :options="addBlockOptions" @select="handleAddBlock">
            <n-button>
              <template #icon>
                <Icon icon="tabler:plus" />
              </template>
              {{ t('Add Block') }}
            </n-button>
          </n-dropdown>
          <n-button type="default" @click="deleteWorkspace" class="delete-btn">
            <template #icon>
              <Icon icon="tabler:trash" />
            </template>
            {{ t('Delete') }}
          </n-button>
          <n-button @click="exitEditMode">
            <template #icon>
              <Icon icon="tabler:x" />
            </template>
            {{ t('Cancel') }}
          </n-button>
          <n-button type="primary" @click="saveChanges" class="save-btn-brand">
            <template #icon>
              <Icon icon="tabler:check" />
            </template>
            {{ t('Save') }}
          </n-button>
        </template>
        <template v-else>
          <n-button quaternary circle @click="enterEditMode" :title="t('Edit Workspace')" class="icon-gray">
            <template #icon>
              <Icon icon="tabler:edit" />
            </template>
          </n-button>
          <n-button
            v-if="hasCreateWorkspaceAccess"
            quaternary
            circle
            @click="openCreateWorkspace"
            :title="t('New Workspace')"
            class="icon-gray"
          >
            <template #icon>
              <Icon icon="tabler:plus" />
            </template>
          </n-button>
        </template>
      </div>
    </div>

    <div v-if="loading" class="loading"></div>
    <div v-else class="content" :class="{ 'edit-mode': isEditMode }">
      <draggable 
        v-model="items" 
        class="grid-12"
        :disabled="!isEditMode"
        item-key="key"
        handle=".drag-handle"
      >
        <template #item="{ element: item, index }">
          <div class="grid-item-wrapper" :class="[item.classes, { 'drag-handle': isEditMode }]">
            <CardBlock
              v-if="item.type==='card'"
              :title="item.title"
              :links="item.links"
              :edit-mode="isEditMode"
              @edit="editBlock(index)"
              @delete="deleteBlock(index)"
            />
            <ShortcutBlock
              v-else-if="item.type==='shortcut'"
              :title="item.title"
              :shortcut-data="item.shortcutData"
              :edit-mode="isEditMode"
              @edit="editBlock(index)"
              @delete="deleteBlock(index)"
            />
            <HeaderBlock
              v-else-if="item.type==='header'"
              :text="item.text"
              :edit-mode="isEditMode"
              @update:text="(val) => updateBlockText(index, val)"
              @delete="deleteBlock(index)"
            />
            <SpacerBlock
              v-else-if="item.type==='spacer'"
              :edit-mode="isEditMode"
              @delete="deleteBlock(index)"
            />
            <ParagraphBlock
              v-else-if="item.type==='paragraph'"
              :text="item.text"
              :edit-mode="isEditMode"
              @update:text="(val) => updateBlockText(index, val)"
              @delete="deleteBlock(index)"
            />
            <ChartBlock
              v-else-if="item.type==='chart'"
              :chart-name="item.chart_name"
              :label="item.label || item.chart_name"
              :chart-settings="item.chart_settings || {}"
              :edit-mode="isEditMode"
              :height="240"
              @edit="editBlock(index)"
              @delete="deleteBlock(index)"
            />
            <OnboardingBlock
              v-else-if="item.type==='onboarding'"
              :onboarding-name="item.onboarding_name"
              :onboarding-data="item.onboardingData"
              :edit-mode="isEditMode"
              @edit="editBlock(index)"
              @delete="deleteBlock(index)"
            />
            <QuickListBlock
              v-else-if="item.type==='quick_list'"
              :quick-list-name="item.quick_list_name"
              :quick-list-data="item.quickListData"
              :edit-mode="isEditMode"
              @edit="editBlock(index)"
              @delete="deleteBlock(index)"
            />
            <NumberCardBlock
              v-else-if="item.type==='number_card'"
              :number-card-name="item.number_card_name"
              :number-card-data="item.numberCardData"
              :edit-mode="isEditMode"
              @edit="editBlock(index)"
              @expand="expandBlock(index)"
              @shrink="shrinkBlock(index)"
              @delete="deleteBlock(index)"
            />
            <CustomBlock
              v-else-if="item.type==='custom_block'"
              :custom-block-name="item.custom_block_name"
              :custom-block-data="item.customBlockData"
              :edit-mode="isEditMode"
              @edit="editBlock(index)"
              @delete="deleteBlock(index)"
            />
          </div>
        </template>
      </draggable>
    </div>
    
    <!-- Widget Dialogs -->
    <HeaderDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'header'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <ParagraphDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'paragraph'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <CardDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'card'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <ChartDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'chart'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <ShortcutDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'shortcut'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <OnboardingDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'onboarding'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <QuickListDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'quick_list'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <NumberCardDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'number_card'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />
    <CustomBlockDialog
      v-model:show="dialogState.show"
      v-if="dialogState.type === 'custom_block'"
      :values="dialogState.values"
      @submit="handleDialogSubmit"
    />

    <!-- Create Workspace Modal (aligned with desk "New Workspace") -->
    <n-modal v-model:show="createWorkspaceState.show" preset="dialog" :title="t('New Workspace')">
      <n-form :model="createWorkspaceState.form" label-width="100">
        <n-form-item :label="t('Title')" required>
          <n-input v-model:value="createWorkspaceState.form.title" :placeholder="t('Enter workspace title')" />
        </n-form-item>

        <n-form-item :label="t('Parent')">
          <n-select
            v-model:value="createWorkspaceState.form.parent"
            :options="parentWorkspaceOptions"
            clearable
            :placeholder="t('None')"
          />
        </n-form-item>

        <n-form-item :label="t('Public')">
          <n-checkbox
            v-model:checked="createWorkspaceState.form.isPublic"
            :disabled="!hasWorkspaceManagerAccess"
            :checked-value="1"
            :unchecked-value="0"
          >
            {{ t('Public') }}
          </n-checkbox>
        </n-form-item>

        <n-form-item :label="t('Icon')">
          <IconPicker v-model="createWorkspaceState.form.icon" />
        </n-form-item>
      </n-form>
      <template #action>
        <n-space>
          <n-button @click="createWorkspaceState.show = false">{{ t('Cancel') }}</n-button>
          <n-button type="primary" :loading="createWorkspaceState.submitting" @click="submitCreateWorkspace">
            {{ t('Create') }}
          </n-button>
        </n-space>
      </template>
    </n-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NButton, NDropdown, NInput, NModal, NForm, NFormItem, NSelect, NCheckbox, NTooltip, useMessage, useDialog } from 'naive-ui'
import { Icon } from '@iconify/vue'
import { t } from '@/shared/i18n'
import { api, getWorkspace, getRecords, saveWorkspaceLayout, deleteRecord } from '@/shared/api/common'
import { pageTypeToSlug } from '@/shared/utils/slug'
import { usePermissionStore } from '@/shared/stores/permissions'
import { useAuthStore } from '@/shared/stores/auth'
import { useMenuStore } from '@/shared/stores/menu'
import { useWorkspaceEditStore } from '@/shared/stores/workspaceEdit'
import { getDesktopPage } from '@/shared/api/workspace'
import draggable from 'vuedraggable'
import IconPicker from '@/core/components/IconPicker.vue'
import OnboardingBlock from '@/core/features/workspace_builder/blocks/OnboardingBlock.vue'
import NumberCardBlock from '@/core/features/workspace_builder/blocks/NumberCardBlock.vue'
import CardBlock from '@/core/features/workspace_builder/blocks/CardBlock.vue'
import ShortcutBlock from '@/core/features/workspace_builder/blocks/ShortcutBlock.vue'
import HeaderBlock from '@/core/features/workspace_builder/blocks/HeaderBlock.vue'
import ParagraphBlock from '@/core/features/workspace_builder/blocks/ParagraphBlock.vue'
import SpacerBlock from '@/core/features/workspace_builder/blocks/SpacerBlock.vue'
import ChartBlock from '@/core/features/workspace_builder/blocks/ChartBlock.vue'
import QuickListBlock from '@/core/features/workspace_builder/blocks/QuickListBlock.vue'
import CustomBlock from '@/core/features/workspace_builder/blocks/CustomBlock.vue'
// Import widget dialogs
import ChartDialog from '@/core/features/workspace_builder/dialogs/ChartDialog.vue'
import ShortcutDialog from '@/core/features/workspace_builder/dialogs/ShortcutDialog.vue'
import CardDialog from '@/core/features/workspace_builder/dialogs/CardDialog.vue'
import OnboardingDialog from '@/core/features/workspace_builder/dialogs/OnboardingDialog.vue'
import QuickListDialog from '@/core/features/workspace_builder/dialogs/QuickListDialog.vue'
import NumberCardDialog from '@/core/features/workspace_builder/dialogs/NumberCardDialog.vue'
import CustomBlockDialog from '@/core/features/workspace_builder/dialogs/CustomBlockDialog.vue'
import HeaderDialog from '@/core/features/workspace_builder/dialogs/HeaderDialog.vue'
import ParagraphDialog from '@/core/features/workspace_builder/dialogs/ParagraphDialog.vue'

const route = useRoute()
const router = useRouter()
const message = useMessage()
const dialog = useDialog()
const permissionStore = usePermissionStore()
const authStore = useAuthStore()
const menuStore = useMenuStore()
const workspaceEditStore = useWorkspaceEditStore()

// Check if this is a private workspace route
const isPrivateRoute = computed(() => route.path.includes('/workspace/private/'))
const routeSlug = computed(() => String(route.params.name || 'build'))

// Lookup workspace from dictionary (like jingrow.workspaces in old frontend)
const workspaceFromDict = computed(() => {
  const slug = routeSlug.value
  if (isPrivateRoute.value) {
    // Private workspace: try slug-username combination
    const username = authStore.user?.name?.toLowerCase() || ''
    const privateKey = `${slug}-${username}`
    return menuStore.workspaces[privateKey]
  } else {
    // Public workspace: directly use slug
    return menuStore.workspaces[slug]
  }
})

// Actual workspace name for API calls (from dictionary)
const workspaceName = computed(() => {
  return workspaceFromDict.value?.name || ''
})

const loading = ref(true)
const pageTitle = ref('Workspace')
const isPublic = ref(true)
const items = ref<any[]>([])
// Use global edit mode from store
const isEditMode = computed(() => workspaceEditStore.isEditMode)
const originalItems = ref<any[]>([])

// Workspace creation meta (aligned with desk)
const workspaceSidebarMeta = ref({
  loaded: false,
  has_access: false,
  has_create_access: false,
  publicParents: [] as string[],
  privateParents: [] as string[]
})

const hasWorkspaceManagerAccess = computed(() => Boolean(workspaceSidebarMeta.value.has_access))
const hasCreateWorkspaceAccess = computed(() => Boolean(workspaceSidebarMeta.value.has_create_access))

// Dialog states
const dialogState = ref({
  type: '' as string,
  show: false,
  isEdit: false,
  editIndex: -1,
  values: null as any
})

const addBlockOptions = [
  { label: t('Heading'), key: 'header', icon: () => h(Icon, { icon: 'tabler:heading' }) },
  { label: t('Text'), key: 'paragraph', icon: () => h(Icon, { icon: 'tabler:text-caption' }) },
  { label: t('Card'), key: 'card', icon: () => h(Icon, { icon: 'tabler:layout-cards' }) },
  { label: t('Chart'), key: 'chart', icon: () => h(Icon, { icon: 'tabler:chart-bar' }) },
  { label: t('Shortcut'), key: 'shortcut', icon: () => h(Icon, { icon: 'tabler:link' }) },
  { label: t('Spacer'), key: 'spacer', icon: () => h(Icon, { icon: 'tabler:minus' }) },
  { label: t('Onboarding'), key: 'onboarding', icon: () => h(Icon, { icon: 'tabler:checklist' }) },
  { label: t('Quick List'), key: 'quick_list', icon: () => h(Icon, { icon: 'tabler:list' }) },
  { label: t('Number Card'), key: 'number_card', icon: () => h(Icon, { icon: 'tabler:numbers' }) },
  { label: t('Custom Block'), key: 'custom_block', icon: () => h(Icon, { icon: 'tabler:code' }) }
]

const tooltipStyle: Record<string, string> = {
  fontSize: '12px',
  padding: '4px 8px',
  background: '#fff',
  color: '#333',
  borderRadius: '4px',
  boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
  border: '1px solid #e5e5e5'
}

function handleAddBlock(key: string) {
  addNewBlock(key)
}

async function loadWorkspaceSidebarMeta(force = false) {
  if (workspaceSidebarMeta.value.loaded && !force) return
  try {
    await menuStore.loadFromBackend()
    const pages = Object.values(menuStore.workspaces)
    const uniq = (arr: string[]) => Array.from(new Set(arr.filter(Boolean)))

    const publicParents = uniq(
      pages
        .filter((p: any) => (p.public === 1 || p.public === true) && (!p.parent_page || p.parent_page === ''))
        .map((p: any) => String(p.title || p.name || '').trim())
    )
    const privateParents = uniq(
      pages
        .filter((p: any) => (p.public === 0 || p.public === false) && (!p.parent_page || p.parent_page === ''))
        .map((p: any) => String(p.title || p.name || '').trim())
    )

    workspaceSidebarMeta.value = {
      loaded: true,
      has_access: menuStore.hasWorkspaceAccess,
      has_create_access: menuStore.hasCreateWorkspaceAccess,
      publicParents,
      privateParents
    }
  } catch {
    // ignore: creation button will be hidden if cannot load
    workspaceSidebarMeta.value.loaded = true
  }
}

async function load() {
  await menuStore.loadFromBackend()

  // If workspace not found in dictionary, it doesn't exist
  if (!workspaceName.value) {
    message.error(t('Workspace not found'))
    loading.value = false
    return
  }
  
  loading.value = true
  const { success, data, message: err } = await getWorkspace(workspaceName.value)
  if (!success) {
    message.error(err || t('Failed to load workspace'))
    loading.value = false
    return
  }

  pageTitle.value = data?.title || workspaceFromDict.value?.title || workspaceName.value
  isPublic.value = Boolean(data?.public ?? true)

  // 调用后端 get_desktop_page API 获取带权限过滤的数据
  // 这个 API 会根据用户权限过滤 cards、shortcuts、quick_lists 等内容
  let filteredData: any = {}
  try {
    filteredData = await getDesktopPage(data)
  } catch (error: any) {
    // 如果权限过滤 API 失败，使用空数据（避免显示未授权内容）
    filteredData = {
      cards: { items: [] },
      shortcuts: { items: [] },
      quick_lists: { items: [] },
      number_cards: { items: [] },
      custom_blocks: { items: [] },
      charts: { items: [] },
      onboardings: { items: [] }
    }
  }

  // 解析 content（布局）
  const layout = parseJSON(data?.content) as Array<any>
  
  // 从后端过滤后的数据中获取各种 block 数据
  const filteredCards = filteredData.cards?.items || []
  const filteredShortcuts = filteredData.shortcuts?.items || []
  const filteredQuickLists = filteredData.quick_lists?.items || []
  const filteredNumberCards = filteredData.number_cards?.items || []
  const filteredCustomBlocks = filteredData.custom_blocks?.items || []
  const filteredCharts = filteredData.charts?.items || []
  const filteredOnboardings = filteredData.onboardings?.items || []

  // Load user's dashboard chart settings (timespan, interval, filters per chart)
  if (filteredCharts.length > 0) {
    try {
      const settingsResult = await api.call('jingrow.client.get_list', {
        pagetype: 'Dashboard Settings',
        filters: {},
        fields: ['chart_config'],
        limit_page_length: 1
      })
      const settingsRecords = settingsResult.message || settingsResult
      if (Array.isArray(settingsRecords) && settingsRecords.length > 0) {
        const chartConfig = settingsRecords[0].chart_config
          ? JSON.parse(settingsRecords[0].chart_config)
          : {}
        filteredCharts.forEach((chart: any) => {
          chart.chart_settings = chartConfig[chart.chart_name] || {}
        })
      }
    } catch {
      // ignore: chart_settings will be empty
    }
  }

  // 将后端过滤后的 cards 按 label 分组，以便按 card_name 查找
  const cardsByLabel: Record<string, any[]> = {}
  for (const card of filteredCards) {
    const label = card.label || 'Untitled'
    if (!cardsByLabel[label]) {
      cardsByLabel[label] = []
    }
    if (card.links) {
      cardsByLabel[label].push(...card.links)
    }
  }

  // 将每个 card 作为一个卡片，col 为 12 栅格宽度；默认 6 ⇒ 两列布局
  const resultItems: any[] = []
  for (const block of layout || []) {
    if (block.type === 'card') {
      const cardName = block.data?.card_name || 'Section'
      const col = Number(block.data?.col || 6)
      
      // 后端返回的 card.label 是翻译后的，需要对 cardName 也进行翻译后再匹配
      const translatedCardName = t(cardName)
      const cardLinks = cardsByLabel[translatedCardName] || []
      
      // 只有当有可用的 links 时才显示 card
      if (cardLinks.length > 0) {
        resultItems.push({ 
          key: `card-${cardName}-${col}-${resultItems.length}`, 
          type: 'card', 
          title: cardName, 
          col, 
          links: cardLinks, 
          classes: mapColToClasses(col) 
        })
      }
    } else if (block.type === 'shortcut') {
      // 处理快捷方式
      const shortcutName = block.data?.shortcut_name || 'Shortcut'
      const col = Number(block.data?.col || 3) // 默认 3 列宽度
      // 后端返回的 label 是翻译后的，需要对 shortcutName 也进行翻译后再匹配
      const translatedShortcutName = t(shortcutName)
      const shortcutData = filteredShortcuts.find((s: any) => s.label === translatedShortcutName)
      
      // 只有当 shortcut 存在且通过权限检查时才显示
      if (shortcutData) {
        resultItems.push({ 
          key: `shortcut-${shortcutName}-${col}-${resultItems.length}`, 
          type: 'shortcut', 
          title: shortcutName, 
          col, 
          shortcutData,
          classes: mapColToClasses(col) 
        })
      }
    } else if (block.type === 'header') {
      // 处理标题
      const text = block.data?.text || 'Header'
      const col = Number(block.data?.col || 12)
      resultItems.push({ 
        key: `header-${text}-${col}-${resultItems.length}`, 
        type: 'header', 
        text, 
        col,
        classes: mapColToClasses(col) 
      })
    } else if (block.type === 'spacer') {
      // 插入占满一行的分隔，仅用于换行
      const col = 12
      resultItems.push({ 
        key: `spacer-${resultItems.length}`, 
        type: 'spacer',
        col,
        classes: mapColToClasses(col) 
      })
    } else if (block.type === 'paragraph') {
      const text = block.data?.text || 'Paragraph'
      const col = Number(block.data?.col || 12)
      resultItems.push({ 
        key: `paragraph-${resultItems.length}`, 
        type: 'paragraph', 
        text, 
        col,
        classes: mapColToClasses(col) 
      })
    } else if (block.type === 'chart') {
      const chartName = block.data?.chart_name || 'Chart'
      const col = Number(block.data?.col || 6)
      // 后端返回的 label 是翻译后的，需要对 chartName 也进行翻译后再匹配
      const translatedChartName = t(chartName)
      // 优先匹配 chart_name，其次匹配翻译后的 label
      const chartData = filteredCharts.find((c: any) => 
        c.chart_name === chartName || c.label === translatedChartName
      )
      
      // 只有当 chart 存在且通过权限检查时才显示
      if (chartData) {
        resultItems.push({ 
          key: `chart-${resultItems.length}`, 
          type: 'chart', 
          chart_name: chartName, 
          label: chartData.label || chartName,
          chart_settings: chartData.chart_settings || {},
          col,
          classes: mapColToClasses(col) 
        })
      }
    } else if (block.type === 'onboarding') {
      const onboardingName = block.data?.onboarding_name || 'Onboarding'
      const col = Number(block.data?.col || 12)
      // 后端返回的 label 是翻译后的，需要对 onboardingName 也进行翻译后再匹配
      const translatedOnboardingName = t(onboardingName)
      const onboardingData = filteredOnboardings.find((o: any) => o.label === translatedOnboardingName)
      
      // 只有当 onboarding 存在且通过权限检查时才显示
      if (onboardingData) {
        resultItems.push({ 
          key: `onboarding-${resultItems.length}`, 
          type: 'onboarding', 
          onboarding_name: onboardingName,
          onboardingData: onboardingData, 
          col,
          classes: ['span-12'] 
        })
      }
    } else if (block.type === 'quick_list') {
      const quickListName = block.data?.quick_list_name || 'Quick List'
      const col = Number(block.data?.col || 6)
      // 后端返回的 label 是翻译后的，需要对 quickListName 也进行翻译后再匹配
      const translatedQuickListName = t(quickListName)
      // 优先匹配 document_type，其次匹配翻译后的 label
      const quickListData = filteredQuickLists.find((q: any) => 
        q.document_type === quickListName || q.label === translatedQuickListName
      )
      
      // 只有当 quick_list 存在且通过权限检查时才显示
      if (quickListData) {
        resultItems.push({ 
          key: `quick_list-${resultItems.length}`, 
          type: 'quick_list', 
          quick_list_name: quickListName, 
          col,
          classes: mapColToClasses(col) 
        })
      }
    } else if (block.type === 'number_card') {
      const numberCardName = block.data?.number_card_name || 'Number Card'
      const col = Number(block.data?.col || 3)
      // 后端返回的 label 是翻译后的，需要对 numberCardName 也进行翻译后再匹配
      const translatedNumberCardName = t(numberCardName)
      const numberCardData = filteredNumberCards.find((n: any) => n.label === translatedNumberCardName)
      
      // 只有当 number_card 存在且通过权限检查时才显示
      if (numberCardData) {
        resultItems.push({ 
          key: `number_card-${resultItems.length}`, 
          type: 'number_card', 
          number_card_name: numberCardName,
          numberCardData: numberCardData, 
          col,
          classes: mapColToClasses(col) 
        })
      }
    } else if (block.type === 'custom_block') {
      const customBlockName = block.data?.custom_block_name || 'Custom Block'
      const col = Number(block.data?.col || 6)
      // 后端返回的 label 是翻译后的，需要对 customBlockName 也进行翻译后再匹配
      const translatedCustomBlockName = t(customBlockName)
      const customBlockData = filteredCustomBlocks.find((cb: any) => cb.label === translatedCustomBlockName)
      
      // 只有当 custom_block 存在且通过权限检查时才显示
      if (customBlockData) {
        resultItems.push({ 
          key: `custom_block-${resultItems.length}`, 
          type: 'custom_block', 
          custom_block_name: customBlockName, 
          col,
          classes: mapColToClasses(col) 
        })
      }
    }
  }
  items.value = resultItems
  originalItems.value = JSON.parse(JSON.stringify(resultItems))

  loading.value = false
}

function refresh() { load() }

function enterEditMode() {
  workspaceEditStore.enterEditMode()
  originalItems.value = JSON.parse(JSON.stringify(items.value))
}

function exitEditMode() {
  workspaceEditStore.exitEditMode()
  items.value = JSON.parse(JSON.stringify(originalItems.value))
}

async function deleteWorkspace() {
  dialog.error({
    title: t('Delete Workspace'),
    content: t('Are you sure you want to delete this workspace?'),
    positiveText: t('Delete'),
    negativeText: t('Cancel'),
    onPositiveClick: async () => {
      try {
        const { success, message: errorMsg } = await deleteRecord('Workspace', workspaceName.value)
        if (success) {
          message.success(t('Deleted successfully'))
          
          // Refresh sidebar menu
          try {
            await menuStore.reloadFromBackend()
          } catch {
            // ignore menu refresh errors
          }
          
          // Navigate to home page
          router.push('/')
        } else {
          message.error(errorMsg || t('Delete failed'))
        }
      } catch (err: any) {
        console.error('Delete workspace error:', err)
        message.error(err?.message || t('Delete failed'))
      }
    }
  })
}

const indicatorColors = [
  'green',
  'cyan',
  'blue',
  'orange',
  'yellow',
  'gray',
  'grey',
  'red',
  'pink',
  'darkgrey',
  'purple',
  'light-blue'
]

const publicOptions = [
  { label: t('Private'), value: 0 },
  { label: t('Public'), value: 1 }
]

const indicatorColorOptions = indicatorColors.map((c) => ({ label: c, value: c }))

const parentWorkspaceOptions = computed(() => {
  const parents = createWorkspaceState.value.form.isPublic === 1
    ? workspaceSidebarMeta.value.publicParents
    : workspaceSidebarMeta.value.privateParents
  return parents.map((p) => ({ label: p, value: p }))
})

const createWorkspaceState = ref({
  show: false,
  submitting: false,
  form: {
    title: '',
    parent: '' as string | null | undefined,
    isPublic: 0 as 0 | 1,
    icon: 'tabler:layout-dashboard',
    indicatorColor: ''
  }
})

async function openCreateWorkspace() {
  await loadWorkspaceSidebarMeta()
  if (!hasCreateWorkspaceAccess.value) {
    message.error(t('No permission to create workspace'))
    return
  }

  createWorkspaceState.value.form = {
    title: '',
    parent: '',
    isPublic: hasWorkspaceManagerAccess.value ? 1 : 0,
    icon: 'tabler:layout-dashboard',
    indicatorColor: ''
  }
  createWorkspaceState.value.show = true
}

async function submitCreateWorkspace() {
  const title = (createWorkspaceState.value.form.title || '').trim()
  if (!title) {
    message.error(t('Please enter workspace title'))
    return
  }

  // desk alignment: non-workspace-manager cannot create public workspaces
  if (createWorkspaceState.value.form.isPublic === 1 && !hasWorkspaceManagerAccess.value) {
    createWorkspaceState.value.form.isPublic = 0
  }

  const isPublic = createWorkspaceState.value.form.isPublic === 1
  const currentUser = authStore.user?.username || authStore.user?.name || ''
  const pgName = isPublic ? title : `${title}-${currentUser}`

  // fast precheck: prevent conflicts when workspace name already exists
  {
    // Use list query instead of `/api/data/Workspace/<name>` to avoid 404 noise in console
    const existing = await getRecords('Workspace', [['name', '=', pgName]], ['name'], 'modified desc', 0, 1)
    if (existing?.success && Array.isArray(existing.data) && existing.data.length > 0) {
      message.error(t('Workspace already exists, please change the title'))
      return
    }
  }

  const blocks = [{ type: 'header', data: { text: `<span class="h4">${title}</span>` } }]

  const newPage: any = {
    content: JSON.stringify(blocks),
    name: pgName,
    label: pgName,
    title,
    public: isPublic ? 1 : 0,
    for_user: isPublic ? '' : currentUser,
    icon: createWorkspaceState.value.form.icon || '',
    indicator_color: '',
    parent_page: createWorkspaceState.value.form.parent || '',
    is_editable: true,
    selected: true
  }

  createWorkspaceState.value.submitting = true
  try {
    // backend expects a JSON string for `new_page` (see workspace.py: new_page -> loads(new_page))
    await api.call('jingrow.desk.pagetype.workspace.workspace.new_page', { new_page: JSON.stringify(newPage) })
    message.success(t('Created successfully'))
    createWorkspaceState.value.show = false

    // refresh sidebar menu (best-effort)
    try {
      await menuStore.reloadFromBackend()
    } catch {
      // ignore
    }

    // Navigate to the new workspace by pg name (route param is workspace name)
    const titleSlug = pageTypeToSlug(title)
    const routePath = isPublic ? `/workspace/${titleSlug}` : `/workspace/private/${titleSlug}`
    router.push(routePath)
  } catch (err: any) {
    const msg = String(err?.message || '')
    if (msg.toLowerCase().includes('name already taken') || msg.includes(t('Name already taken'))) {
      message.error(t('Name already taken, please change the title'))
    } else if (msg.toLowerCase().includes('already exist') || msg.includes(t('Already exists'))) {
      message.error(t('Workspace already exists, please change the title'))
    } else {
      message.error(msg || t('Creation failed'))
    }
  } finally {
    createWorkspaceState.value.submitting = false
  }
}

async function saveChanges() {
  // Build content (layout) format for backend
  const content = items.value.map(item => {
    if (item.type === 'card') {
      return { 
        type: 'card', 
        data: { 
          card_name: item.title, 
          col: item.col,
          links: typeof item.links === 'string' ? item.links : JSON.stringify(item.links || [])
        } 
      }
    } else if (item.type === 'shortcut') {
      return { 
        type: 'shortcut', 
        data: { 
          shortcut_name: item.title, 
          col: item.col,
          ...(item.shortcutData || {})
        } 
      }
    } else if (item.type === 'header') {
      return { type: 'header', data: { text: item.text, col: item.col || 12 } }
    } else if (item.type === 'spacer') {
      return { type: 'spacer', data: {} }
    } else if (item.type === 'paragraph') {
      return { type: 'paragraph', data: { text: item.text || '', col: item.col || 12 } }
    } else if (item.type === 'chart') {
      return { type: 'chart', data: { chart_name: item.chart_name || '', label: item.label || '', col: item.col || 6 } }
    } else if (item.type === 'onboarding') {
      return { type: 'onboarding', data: { onboarding_name: item.onboarding_name || '', col: item.col || 12 } }
    } else if (item.type === 'quick_list') {
      return { 
        type: 'quick_list', 
        data: { 
          document_type: item.document_type || item.quick_list_name || '', 
          label: item.label || '',
          quick_list_filter: item.quick_list_filter || '',
          col: item.col || 6 
        } 
      }
    } else if (item.type === 'number_card') {
      return { type: 'number_card', data: { number_card_name: item.number_card_name || '', label: item.label || '', col: item.col || 3 } }
    } else if (item.type === 'custom_block') {
      return { type: 'custom_block', data: { custom_block_name: item.custom_block_name || '', col: item.col || 6 } }
    }
    return null
  }).filter(Boolean)

  // Build new_widgets format for legacy links table population
  const newWidgets: any = {}
  
  // Collect all widget types that need to be saved to child tables
  const widgetTypes = ['card', 'shortcut', 'chart', 'quick_list', 'number_card', 'custom_block']
  
  widgetTypes.forEach(widgetType => {
    const widgetItems = items.value.filter(item => item.type === widgetType)
    
    if (widgetItems.length > 0) {
      if (widgetType === 'card') {
        newWidgets.card = widgetItems.map(card => ({
          label: card.title,
          links: JSON.stringify(card.links || [])
        }))
      } else if (widgetType === 'shortcut') {
        newWidgets.shortcut = widgetItems.map(shortcut => ({
          label: shortcut.title,
          type: shortcut.shortcutData?.type,
          link_to: shortcut.shortcutData?.link_to,
          url: shortcut.shortcutData?.url,
          pg_view: shortcut.shortcutData?.pg_view,
          color: shortcut.shortcutData?.color,
          format: shortcut.shortcutData?.format,
          stats_filter: shortcut.shortcutData?.stats_filter,
          icon: shortcut.shortcutData?.icon
        }))
      } else if (widgetType === 'chart') {
        newWidgets.chart = widgetItems.map(chart => ({
          chart_name: chart.chart_name,
          label: chart.label
        }))
      } else if (widgetType === 'quick_list') {
        newWidgets.quick_list = widgetItems.map(quickList => ({
          document_type: quickList.document_type || quickList.quick_list_name,
          label: quickList.label,
          quick_list_filter: quickList.quick_list_filter
        }))
      } else if (widgetType === 'number_card') {
        newWidgets.number_card = widgetItems.map(card => ({
          number_card_name: card.number_card_name,
          label: card.label
        }))
      } else if (widgetType === 'custom_block') {
        newWidgets.custom_block = widgetItems.map(block => ({
          custom_block_name: block.custom_block_name
        }))
      }
    }
  })

  try {
    const { success, message: err } = await saveWorkspaceLayout(
      pageTitle.value,
      isPublic.value,
      content,
      newWidgets
    )
    
    if (success) {
      message.success(t('Saved successfully'))
      workspaceEditStore.exitEditMode()
      originalItems.value = JSON.parse(JSON.stringify(items.value))
    } else {
      message.error(err || t('Save failed'))
    }
  } catch (err: any) {
    message.error(err?.message || t('Save failed'))
  }
}

function deleteBlock(index: number) {
  items.value.splice(index, 1)
}

// Block menu options - aligned with legacy Jingrow
function getBlockMenuOptions(index: number) {
  const block = items.value[index]
  const minWidth = 3
  const canExpand = block.col && block.col < 12
  const canShrink = block.col && block.col > minWidth
  
  return [
    { label: t('Delete'), key: 'delete', icon: () => h(Icon, { icon: 'tabler:trash' }) },
    { label: t('Expand'), key: 'expand', icon: () => h(Icon, { icon: 'tabler:arrows-horizontal' }), disabled: !canExpand },
    { label: t('Shrink'), key: 'shrink', icon: () => h(Icon, { icon: 'tabler:arrows-minimize' }), disabled: !canShrink },
    { label: t('Move Up'), key: 'move_up', icon: () => h(Icon, { icon: 'tabler:arrow-up' }), disabled: index === 0 },
    { label: t('Move Down'), key: 'move_down', icon: () => h(Icon, { icon: 'tabler:arrow-down' }), disabled: index === items.value.length - 1 }
  ]
}

function handleBlockMenuSelect(key: string, index: number) {
  switch (key) {
    case 'delete':
      deleteBlock(index)
      break
    case 'expand':
      expandBlock(index)
      break
    case 'shrink':
      shrinkBlock(index)
      break
    case 'move_up':
      moveBlockUp(index)
      break
    case 'move_down':
      moveBlockDown(index)
      break
  }
}

function expandBlock(index: number) {
  const block = items.value[index]
  if (block.col && block.col < 12) {
    // Expand by 1 - aligned with legacy: simply increment
    block.col = block.col + 1
    block.classes = mapColToClasses(block.col)
  }
}

function shrinkBlock(index: number) {
  const block = items.value[index]
  const minWidth = 3
  if (block.col && block.col > minWidth) {
    // Shrink by 1 - aligned with legacy: simply decrement
    block.col = block.col - 1
    block.classes = mapColToClasses(block.col)
  }
}

function moveBlockUp(index: number) {
  if (index > 0) {
    const temp = items.value[index]
    items.value[index] = items.value[index - 1]
    items.value[index - 1] = temp
  }
}

function moveBlockDown(index: number) {
  if (index < items.value.length - 1) {
    const temp = items.value[index]
    items.value[index] = items.value[index + 1]
    items.value[index + 1] = temp
  }
}

function editBlock(index: number) {
  const block = items.value[index]
  const type = block.type
  
  // Prepare values for editing
  let values: any = { name: block.key }
  
  switch (type) {
    case 'header':
    case 'paragraph':
      values.text = block.text
      break
    case 'card':
      values.label = block.title
      values.links = block.links
      break
    case 'chart':
      values.chart_name = block.chart_name
      values.label = block.label
      break
    case 'shortcut':
      values = {
        name: block.key,
        label: block.title,
        ...block.shortcutData
      }
      break
    case 'onboarding':
      values.onboarding_name = block.onboarding_name
      break
    case 'quick_list':
      values.document_type = block.document_type || block.quick_list_name
      values.label = block.label
      break
    case 'number_card':
      values.number_card_name = block.number_card_name
      values.label = block.label
      break
    case 'custom_block':
      values.custom_block_name = block.custom_block_name
      break
  }
  
  dialogState.value = {
    type,
    show: true,
    isEdit: true,
    editIndex: index,
    values
  }
}

function addNewBlock(type: string) {
  if (type === 'spacer') {
    // Spacer doesn't need configuration
    const newBlock = { 
      key: `spacer-${Date.now()}`, 
      type: 'spacer',
      col: 12,
      classes: mapColToClasses(12)
    }
    items.value.push(newBlock)
    return
  }
  
  // Header and paragraph blocks are added directly for inline editing
  if (type === 'header') {
    const newBlock = {
      key: `header-${Date.now()}`,
      type: 'header',
      text: `<span class="h4">${t('Heading')}</span>`,
      col: 12,
      classes: mapColToClasses(12)
    }
    items.value.push(newBlock)
    return
  }
  
  if (type === 'paragraph') {
    const newBlock = {
      key: `paragraph-${Date.now()}`,
      type: 'paragraph',
      text: t('Text'),
      col: 12,
      classes: mapColToClasses(12)
    }
    items.value.push(newBlock)
    return
  }
  
  // Open appropriate dialog for other block types
  dialogState.value = {
    type,
    show: true,
    isEdit: false,
    editIndex: -1,
    values: null
  }
}

function updateBlockText(index: number, text: string) {
  const block = items.value[index]
  if (block.type === 'header') {
    // Preserve HTML wrapper for header
    block.text = `<span class="h4">${text}</span>`
  } else if (block.type === 'paragraph') {
    block.text = text
  }
}

function handleDialogSubmit(data: any) {
  const type = dialogState.value.type
  const isEdit = dialogState.value.isEdit
  const editIndex = dialogState.value.editIndex
  
  if (isEdit && editIndex >= 0) {
    // Update existing block
    const block = items.value[editIndex]
    
    // Type-specific update logic
    if (type === 'card') {
      block.title = data.label
      block.links = data.links ? (typeof data.links === 'string' ? JSON.parse(data.links) : data.links) : []
      if (data.description !== undefined) {
        block.description = data.description
      }
      if (data.col) {
        block.col = data.col
        block.classes = mapColToClasses(data.col)
      }
    } else if (type === 'shortcut') {
      block.title = data.label
      block.shortcutData = {
        type: data.type,
        link_to: data.link_to,
        url: data.url,
        pg_view: data.pg_view,
        color: data.color,
        format: data.format,
        stats_filter: data.stats_filter,
        icon: data.icon
      }
      if (data.col) {
        block.col = data.col
        block.classes = mapColToClasses(data.col)
      }
    } else {
      Object.assign(block, data)
      if (data.col) {
        block.classes = mapColToClasses(data.col)
      }
    }
  } else {
    // Create new block with minimal structure
    const newBlock: any = { 
      key: `${type}-${Date.now()}`, 
      type
    }
    
    // Set column width and responsive classes
    const colWidthMap: Record<string, number> = {
      'card': 6, 'chart': 6,
      'shortcut': 3, 'number_card': 3,
      'quick_list': 6, 'custom_block': 6
    }
    newBlock.col = data.col || colWidthMap[type] || 12
    newBlock.classes = mapColToClasses(newBlock.col)
    
    // Type-specific data mapping
    switch (type) {
      case 'card':
        newBlock.title = data.label
        newBlock.links = data.links ? (typeof data.links === 'string' ? JSON.parse(data.links) : data.links) : []
        break
      case 'shortcut':
        newBlock.title = data.label
        newBlock.shortcutData = {
          type: data.type,
          link_to: data.link_to,
          url: data.url,
          pg_view: data.pg_view,
          color: data.color,
          format: data.format,
          stats_filter: data.stats_filter,
          icon: data.icon
        }
        break
      case 'chart':
        Object.assign(newBlock, { chart_name: data.chart_name, label: data.label })
        break
      case 'onboarding':
        newBlock.onboarding_name = data.onboarding_name
        break
      case 'quick_list':
        Object.assign(newBlock, {
          document_type: data.document_type,
          quick_list_name: data.document_type,
          label: data.label,
          quick_list_filter: data.quick_list_filter
        })
        break
      case 'number_card':
        Object.assign(newBlock, { number_card_name: data.number_card_name, label: data.label })
        break
      case 'custom_block':
        newBlock.custom_block_name = data.custom_block_name
        break
      default:
        Object.assign(newBlock, data)
    }
    
    items.value.push(newBlock)
  }
  
  // Close dialog
  dialogState.value.show = false
}

watch(() => route.params.name, load)
onMounted(async () => {
  await loadWorkspaceSidebarMeta()
  load()
})
</script>

<style scoped>
.workspace { padding: 0 16px; }
.workspace-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 0; margin-bottom: 16px; }
.header-actions { display: flex; align-items: center; gap: 8px; }

/* 删除按钮悬停时显示红色 */
.delete-btn:hover:not(:disabled) {
  background: #ef4444 !important;
  border-color: #ef4444 !important;
  color: white !important;
}

.delete-btn:hover:not(:disabled) :deep(.n-button__border),
.delete-btn:hover:not(:disabled) :deep(.n-button__state-border) {
  border-color: #ef4444 !important;
}

/* 保存按钮品牌样式 */
.save-btn-brand {
  background: #e6f8f0 !important;
  border: 1px solid #1fc76f !important;
  color: #0d684b !important;
}

.save-btn-brand :deep(.n-button__border) {
  border: none !important;
  border-color: transparent !important;
}

.save-btn-brand :deep(.n-button__state-border) {
  border: none !important;
  border-color: transparent !important;
}

.save-btn-brand:hover {
  background: #dcfce7 !important;
  border-color: #1fc76f !important;
  border: 1px solid #1fc76f !important;
  color: #166534 !important;
  box-shadow: 0 2px 8px rgba(31, 199, 111, 0.15) !important;
}

.save-btn-brand:hover :deep(.n-button__border),
.save-btn-brand:hover :deep(.n-button__state-border) {
  border: none !important;
  border-color: transparent !important;
}

.save-btn-brand:focus {
  background: #dcfce7 !important;
  border-color: #1fc76f !important;
  border: 1px solid #1fc76f !important;
  color: #166534 !important;
  box-shadow: 0 0 0 2px rgba(31, 199, 111, 0.2) !important;
}

.save-btn-brand:focus :deep(.n-button__border),
.save-btn-brand:focus :deep(.n-button__state-border) {
  border: none !important;
  border-color: transparent !important;
}

.save-btn-brand:active {
  background: #1fc76f !important;
  border-color: #1fc76f !important;
  border: 1px solid #1fc76f !important;
  color: white !important;
  box-shadow: 0 1px 4px rgba(31, 199, 111, 0.2) !important;
}

.save-btn-brand:active :deep(.n-button__border),
.save-btn-brand:active :deep(.n-button__state-border) {
  border: none !important;
  border-color: transparent !important;
}

.save-btn-brand:disabled {
  background: #f1f5f9 !important;
  border: 1px solid #e2e8f0 !important;
  border-color: #e2e8f0 !important;
  color: #94a3b8 !important;
  opacity: 0.6 !important;
  cursor: not-allowed !important;
}

.save-btn-brand:disabled :deep(.n-button__border),
.save-btn-brand:disabled :deep(.n-button__state-border) {
  border: none !important;
  border-color: transparent !important;
}

/* 灰色图标按钮 */
.icon-gray {
  color: #64748b !important;
}

.icon-gray:hover {
  color: #475569 !important;
  background: #f1f5f9 !important;
}
.title-wrap { display: flex; align-items: center; gap: 8px; }
.title { margin: 0; font-size: 20px; }
.content { min-height: calc(100vh - 160px); }
.content.edit-mode { background: #f8fafc; padding: 16px; border-radius: 8px; }
.grid-12 { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 16px; }

.grid-item-wrapper { position: relative; }

.edit-mode .grid-item-wrapper.drag-handle { cursor: move; }

.edit-mode .grid-item-wrapper.drag-handle:hover .card,
.edit-mode .grid-item-wrapper.drag-handle:hover .shortcut,
.edit-mode .grid-item-wrapper.drag-handle:hover .header,
.edit-mode .grid-item-wrapper.drag-handle:hover .spacer,
.edit-mode .grid-item-wrapper.drag-handle:hover .paragraph,
.edit-mode .grid-item-wrapper.drag-handle:hover .chart-block,
.edit-mode .grid-item-wrapper.drag-handle:hover .onboarding-block,
.edit-mode .grid-item-wrapper.drag-handle:hover .quick-list-block,
.edit-mode .grid-item-wrapper.drag-handle:hover .number-card-block,
.edit-mode .grid-item-wrapper.drag-handle:hover .custom-block {
  border-color: #18a058;
  box-shadow: 0 4px 12px rgba(24, 160, 88, 0.15);
}

/* 基线：移动端单列 */
.span-12 { grid-column: span 12; }
/* Bootstrap aligned breakpoints: sm=576, md=768, lg=992 */
@media (min-width: 576px) { .sm-span-6 { grid-column: span 6; } }
@media (min-width: 768px) { .md-span-4 { grid-column: span 4; } }
@media (min-width: 992px) { 
  .lg-span-11 { grid-column: span 11; }
  .lg-span-10 { grid-column: span 10; }
  .lg-span-9 { grid-column: span 9; }
  .lg-span-8 { grid-column: span 8; }
  .lg-span-7 { grid-column: span 7; }
  .lg-span-3 { grid-column: span 3; }
  .lg-span-2 { grid-column: span 2; }
}

.loading { color: #64748b; }
@media (max-width: 1024px) { .grid-12 { grid-template-columns: 1fr; } }

/* Override Naive UI tooltip dark background */
:deep(.n-tooltip__content) {
  background: #fff !important;
  color: #333 !important;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
  border: 1px solid #e5e5e5 !important;
  padding: 4px 8px !important;
  font-size: 12px !important;
  border-radius: 4px !important;
}
</style>

<script lang="ts">
// 本地工具：安全解析 JSON
export function parseJSON(input: any): any[] {
  try {
    if (typeof input === 'string') return JSON.parse(input)
    if (Array.isArray(input)) return input
    return []
  } catch {
    return []
  }
}

// 将 jingrow 的 set_col_class 规则映射到 CSS Grid 的响应式 span 类
// 完全对齐旧版逻辑：width 7-12每个值都不同
export function mapColToClasses(width: number): string[] {
  const classes: string[] = []
  
  if (width <= 12 && width >= 7) {
    // 大卡：7-12 每个宽度都单独处理
    // 对应旧版：col-xs-{width}
    // 在CSS Grid中，我们需要为每个宽度创建对应的类
    if (width === 12) {
      classes.push('span-12')
    } else if (width === 11) {
      classes.push('span-12', 'lg-span-11')
    } else if (width === 10) {
      classes.push('span-12', 'lg-span-10')
    } else if (width === 9) {
      classes.push('span-12', 'lg-span-9')
    } else if (width === 8) {
      classes.push('span-12', 'lg-span-8')
    } else if (width === 7) {
      classes.push('span-12', 'lg-span-7')
    }
  } else if (width === 6 || width === 5) {
    classes.push('span-12', 'sm-span-6')
  } else if (width === 4) {
    classes.push('span-12', 'sm-span-6', 'md-span-4')
  } else if (width === 3 || width === 2) {
    classes.push('span-12', 'sm-span-6', 'md-span-4', `lg-span-${width}`)
  }
  
  return classes
}
</script>


