<template>
  <div class="app-sidebar" :class="{ 'edit-mode': workspaceEditStore.isEditMode }">
    <div class="sidebar-header">
      <div class="logo">
        <router-link to="/" class="logo-link">
          <img src="/logo.svg" :alt="appName" width="32" height="32" />
          <span v-if="!collapsed" class="logo-text">{{ appName }}</span>
        </router-link>
      </div>
    </div>

    <div class="menu-container">
      <n-menu
        v-if="!workspaceEditStore.isEditMode"
        :collapsed="collapsed"
        :collapsed-width="64"
        :collapsed-icon-size="24"
        :options="menuOptions"
        :value="currentRoute"
        :render-icon="renderMenuIcon"
        :render-label="renderMenuLabel"
        @update:value="handleMenuSelect"
      />
      
      <!-- Edit mode: show workspace items with controls -->
      <div v-else class="edit-menu">
        <draggable 
          v-model="menuStore.editableWorkspaceOrder" 
          item-key="id"
          @end="handleSidebarDragEnd"
        >
          <template #item="{ element }">
            <div class="menu-item-wrapper">
              <div class="menu-item-edit" :class="{ 'is-hidden': element.hidden, 'has-parent': element.parentId }">
                <div class="item-content">
                  <DynamicIcon :name="element.icon" :size="20" />
                  <span class="item-label">{{ t(element.label) }}</span>
                </div>
                <div class="item-actions">
                  <n-dropdown trigger="click" :options="getMenuOptions(element)" @select="(key) => handleMenuAction(key, element)">
                    <n-button quaternary size="tiny">
                      <template #icon><Icon icon="tabler:dots-vertical" :size="16" /></template>
                    </n-button>
                  </n-dropdown>
                </div>
              </div>
            </div>
          </template>
        </draggable>
      </div>
    </div>
    
    <!-- Workspace Edit Dialog -->
    <WorkspaceDialog
      v-model:show="editDialogState.show"
      :is-edit="true"
      :workspace="editDialogState.workspace"
      :parent-options="parentWorkspaceOptions"
      :has-access="true"
      @submit="handleEditSubmit"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, h, onMounted, ref, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { NMenu, NButton, NDropdown, useMessage, useDialog } from 'naive-ui'
import { Icon } from '@iconify/vue'
import draggable from 'vuedraggable'
import { t } from '../../shared/i18n'
import { useMenuStore, type AppMenuItem } from '../../shared/stores/menu'
import { useWorkspaceEditStore } from '../../shared/stores/workspaceEdit'
import { pageTypeToSlug } from '../../shared/utils/slug'
import DynamicIcon from '../../core/components/DynamicIcon.vue'
import WorkspaceDialog from '../../views/workspace/WorkspaceDialog.vue'
import { api } from '../../shared/api/common'

interface Props {
  collapsed: boolean
}

defineProps<Props>()

const emit = defineEmits<{
  'menu-select': []
}>()

const router = useRouter()
const route = useRoute()
const message = useMessage()
const dialog = useDialog()

const currentRoute = computed(() => route.name as string)

const menuStore = useMenuStore()
const workspaceEditStore = useWorkspaceEditStore()

const appName = computed(() => localStorage.getItem('appName') || 'Jingrow')

const editDialogState = ref({ show: false, workspace: null as AppMenuItem | null })

const parentWorkspaceOptions = computed(() => {
  const currentWorkspace = editDialogState.value.workspace
  if (!currentWorkspace) return []
  
  // Use isPrivate field to determine workspace type
  const isPrivate = currentWorkspace.isPrivate ?? false
  
  // Filter workspaces: only same type (public/private) and exclude current workspace
  return menuStore.editableWorkspaceOrder
    .filter(w => {
      // Exclude current workspace itself
      if (w.id === currentWorkspace.id) return false
      
      // Only include workspaces of the same type
      const wIsPrivate = w.isPrivate ?? false
      return wIsPrivate === isPrivate
    })
    .map(w => ({ label: w.label, value: w.label }))
})

onMounted(async () => {
  await menuStore.loadFromBackend()
  syncEditableWorkspaces()
})

watch(() => workspaceEditStore.isEditMode, (isEdit) => {
  if (isEdit) syncEditableWorkspaces()
})

function syncEditableWorkspaces() {
  const workspaceItems = menuStore.items
    .filter(item => item.type === 'workspace')
    .map(item => ({ ...item }))
  
  // Sort to ensure parent items come before their children
  const sorted: AppMenuItem[] = []
  
  // First add all root items (items without parent)
  workspaceItems.forEach(item => {
    if (!item.parentId) {
      sorted.push(item)
      // Then add all children of this parent
      workspaceItems.forEach(child => {
        if (child.parentId === item.id || child.parentId === item.workspaceName) {
          sorted.push(child)
        }
      })
    }
  })
  
  menuStore.editableWorkspaceOrder = sorted
}

function getMenuOptions(workspace: AppMenuItem) {
  return [
    { label: t('Edit'), key: 'edit', icon: () => h(Icon, { icon: 'tabler:edit', size: 16 }) },
    { label: workspace.hidden ? t('Show') : t('Hide'), key: 'toggle-hide', icon: () => h(Icon, { icon: workspace.hidden ? 'tabler:eye' : 'tabler:eye-off', size: 16 }) },
    ...(!workspace.workspaceName?.startsWith('Build') ? [{ label: t('Delete'), key: 'delete', icon: () => h(Icon, { icon: 'tabler:trash', size: 16 }) }] : [])
  ]
}

function handleMenuAction(key: string, workspace: AppMenuItem) {
  const actions: Record<string, () => void> = {
    edit: () => editWorkspace(workspace),
    'toggle-hide': () => toggleHideWorkspace(workspace),
    delete: () => confirmDeleteWorkspace(workspace)
  }
  actions[key]?.()
}

async function handleSidebarDragEnd() {
  try {
    const workspaceItems = menuStore.editableWorkspaceOrder
    if (!workspaceItems || workspaceItems.length === 0) return

    const publicItems = workspaceItems
      .filter(item => !item.isPrivate)
      .map(item => ({
        title: item.label,
        parent_page: item.parentId || '',
        public: 1
      }))

    const privateItems = workspaceItems
      .filter(item => item.isPrivate)
      .map(item => ({
        title: item.label,
        parent_page: item.parentId || '',
        public: 0
      }))

    if (publicItems.length > 0 || privateItems.length > 0) {
      await api.call('jingrow.desk.pagetype.workspace.workspace.sort_pages', {
        sb_public_items: JSON.stringify(publicItems),
        sb_private_items: JSON.stringify(privateItems)
      })
      await menuStore.reloadFromBackend()
    }
  } catch (err) {
    console.error('Failed to save sidebar sort order:', err)
  }
}

async function editWorkspace(workspace: AppMenuItem) {
  await menuStore.loadFromBackend()
  syncEditableWorkspaces()
  
  // Convert parentId (name with user suffix) to parent label (title without suffix)
  const processedWorkspace = { ...workspace }
  if (processedWorkspace.parentId) {
    const parentItem = menuStore.editableWorkspaceOrder.find(w => w.workspaceName === processedWorkspace.parentId)
    if (parentItem) {
      processedWorkspace.parentId = parentItem.label
    }
  }
  
  editDialogState.value = { show: true, workspace: processedWorkspace }
}

async function handleEditSubmit(form: any) {
  try {
    await api.call('jingrow.desk.pagetype.workspace.workspace.update_page', {
      name: editDialogState.value.workspace?.workspaceName,
      title: form.title,
      icon: form.icon || '',
      indicator_color: '',  // No longer used, but kept for backend compatibility
      parent: form.parent || '',
      public: form.isPublic || 0
    })
    
    editDialogState.value.show = false
    message.success(t('Updated'))
    await menuStore.loadFromBackend()
    syncEditableWorkspaces()
  } catch (error: any) {
    message.error(error.message || t('Error'))
  }
}

async function toggleHideWorkspace(workspace: AppMenuItem) {
  try {
    const method = workspace.hidden ? 'unhide_page' : 'hide_page'
    await api.call(`jingrow.desk.pagetype.workspace.workspace.${method}`, {
      page_name: workspace.workspaceName
    })
    
    workspace.hidden = !workspace.hidden
    await menuStore.loadFromBackend()
    syncEditableWorkspaces()
  } catch (error: any) {
    message.error(error.message || t('Error'))
  }
}

function confirmDeleteWorkspace(workspace: AppMenuItem) {
  dialog.warning({
    title: t('Delete'),
    content: t('Are you sure?'),
    positiveText: t('Delete'),
    negativeText: t('Cancel'),
    onPositiveClick: () => deleteWorkspace(workspace)
  })
}

async function deleteWorkspace(workspace: AppMenuItem) {
  try {
    await api.call('jingrow.desk.pagetype.workspace.workspace.delete_page', {
      page: JSON.stringify({
        name: workspace.workspaceName,
        title: workspace.label,
        public: !workspace.workspaceName?.includes('-') ? 1 : 0
      })
    })
    
    await menuStore.loadFromBackend()
    syncEditableWorkspaces()
    message.success(t('Deleted'))
  } catch (error: any) {
    message.error(error.message || t('Error'))
  }
}
type MenuOption = {
  label: string
  key: string
  icon?: any
  children?: MenuOption[]
}

const buildTree = (items: AppMenuItem[]) => {
  const byId: Record<string, AppMenuItem & { children: (AppMenuItem & { children?: any[] })[] }> = {}
  items.forEach((i: AppMenuItem) => (byId[i.id] = { ...(i as any), children: [] }))
  const roots: (AppMenuItem & { children: any[] })[] = []
  items.forEach((i: AppMenuItem) => {
    const pid = (i as any).parentId as string | null | undefined
    if (pid && byId[pid]) byId[pid].children.push(byId[i.id])
    else roots.push(byId[i.id])
  })
  return roots
}

const renderIcon = (name?: string, size = 24) =>
  name
    ? () => h(DynamicIcon, { name, size, color: '#64748b' })
    : undefined

const toMenuOptions = (nodes: (AppMenuItem & { children?: any[] })[]): MenuOption[] => {
  const options: MenuOption[] = []
  let hasAddedDivider = false
  
  nodes.forEach((n: any, index: number) => {
    // Check if this is the first public workspace after private ones
    if (!hasAddedDivider && !n.isPrivate) {
      const hasPreviousPrivate = nodes.slice(0, index).some(item => item.isPrivate)
      if (hasPreviousPrivate) {
        // Add visual separator before public workspaces
        options.push({
          type: 'divider',
          key: 'workspace-divider'
        } as any)
        hasAddedDivider = true
      }
    }
    
    options.push({
      label: t(n.label),
      key: n.id,
      icon: renderIcon(n.icon, 24),
      children: n.children && n.children.length
        ? n.children.map((c: any) => ({
            label: t(c.label),
            key: c.id,
            icon: renderIcon(c.icon, 20),
            children: c.children?.length ? toMenuOptions(c.children as any) : undefined
          }))
        : undefined
    })
  })
  
  return options
}

const menuOptions = computed(() => {
  const tree = buildTree(menuStore.visibleItems)
  return toMenuOptions(tree)
})

const renderMenuIcon = (option: MenuOption) => {
  return h('div', {
    onClick: (e: Event) => {
      if (option.children && option.children.length > 0) {
        e.stopPropagation()
        handleMenuSelect(option.key)
      }
    }
  }, option.icon ? option.icon() : null)
}

const renderMenuLabel = (option: MenuOption) => {
  return h('span', {
    onClick: (e: Event) => {
      if (option.children && option.children.length > 0) {
        e.stopPropagation()
        handleMenuSelect(option.key)
      }
    }
  }, option.label)
}

const handleMenuSelect = (key: string) => {
  const menuItem = menuStore.items.find(item => item.id === key)
  if (!menuItem) return
  
  emit('menu-select')
  
  if (menuItem.type === 'pagetype' && menuItem.pagetype) {
    const slug = pageTypeToSlug(menuItem.pagetype)
    router.push({ name: 'PageTypeList', params: { entity: slug } })
  } else if (menuItem.type === 'route' && menuItem.routeName) {
    router.push({ name: menuItem.routeName })
  } else if (menuItem.type === 'url' && menuItem.url) {
    if (menuItem.url.startsWith('http://') || menuItem.url.startsWith('https://')) {
      window.open(menuItem.url, '_blank')
    } else {
      router.push(menuItem.url)
    }
  } else {
    if (menuItem.type === 'workspace' && menuItem.workspaceName) {
      // Generate workspace route based on public/private status
      const slug = pageTypeToSlug(menuItem.label)
      const routePath = menuItem.isPrivate ? `/workspace/private/${slug}` : `/workspace/${slug}`
      router.push(routePath)
      return
    }
    if (menuItem.url) {
      if (menuItem.url.startsWith('http://') || menuItem.url.startsWith('https://')) {
        window.open(menuItem.url, '_blank')
      } else {
        router.push(menuItem.url)
      }
    } else if (menuItem.routeName) {
      router.push({ name: menuItem.routeName })
    }
  }
}
</script>

<style scoped>
.app-sidebar {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.sidebar-header {
  padding: 16px;
  border-bottom: 1px solid var(--border-color);
  flex-shrink: 0;
}

.menu-container {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}
.menu-container::-webkit-scrollbar { width: 2px; }
.menu-container::-webkit-scrollbar-track { background: transparent; }
.menu-container::-webkit-scrollbar-thumb { background: transparent; border-radius: 3px; }
.app-sidebar:hover .menu-container::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); }

.logo {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 16px;
  font-weight: 700;
  color: #1f2937;
}

.logo-link {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: inherit;
  text-decoration: none;
}

.logo-text {
  white-space: nowrap;
}

:deep(.n-menu-item-content) {
  transition: all 0.2s ease;
}

:deep(.n-menu-item-content:hover) {
  background-color: rgba(24, 160, 88, 0.1);
}

:deep(.n-menu-item-content.n-menu-item-content--selected) {
  background-color: rgba(24, 160, 88, 0.15);
}

:deep(.n-menu-item-content.n-menu-item-content--selected .n-icon) {
  color: #18a058 !important;
}

:deep(.n-menu-item-content:hover .n-icon) {
  color: #18a058 !important;
  transform: scale(1.1);
}

/* Edit mode styles */
.edit-menu {
  padding: 8px;
}

.menu-item-wrapper {
  margin-bottom: 4px;
}

.menu-item-edit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-radius: 6px;
  background: white;
  border: 1px solid #e5e7eb;
  transition: all 0.2s;
  cursor: move;
}

/* Child menu items with indentation */
.menu-item-edit.has-parent {
  margin-left: 24px;
  background: #f9fafb;
}

.menu-item-edit:hover {
  border-color: #18a058;
  box-shadow: 0 2px 8px rgba(24, 160, 88, 0.15);
}

.menu-item-edit.is-hidden {
  opacity: 0.5;
}

.item-content {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}

.item-label {
  flex: 1;
  font-size: 14px;
  color: #1f2937;
}

.item-actions {
  display: flex;
  gap: 4px;
}

.edit-mode .menu-container {
  background: #f9fafb;
}

/* Workspace divider styles */
:deep(.n-menu-divider) {
  margin: 16px 12px;
  height: 1px;
  background-color: var(--border-color, #e5e7eb);
}
</style>
