<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import type { KbxNavigationResolvedEntry, KbxNavigationSection, KbxRecentNavigation, KbxWorkspaceTab } from '@kbx/contracts'
import KbxGlobalHeader from './KbxGlobalHeader.vue'
import KbxMenuSearch from './KbxMenuSearch.vue'
import KbxSideNavigation from './KbxSideNavigation.vue'
import KbxWorkspaceTabs from './KbxWorkspaceTabs.vue'

const props=withDefaults(defineProps<{productName?:string;activeModule?:string;activeScreenId?:string|null;sections:KbxNavigationSection[];allEntries:KbxNavigationResolvedEntry[];favorites?:KbxNavigationResolvedEntry[];recents?:KbxRecentNavigation[];tabs?:KbxWorkspaceTab[];activeTabKey?:string|null;sideNavCollapsed?:boolean;menuSearchOpen?:boolean;operationCount?:number;notificationCount?:number;operationsOpen?:boolean;notificationsOpen?:boolean;homeActive?:boolean;workspaceMaxTabs?:number;shellNotice?:string|null;themeMode?:'light'|'dark'}>(),{productName:'KBX',activeModule:'',activeScreenId:null,favorites:()=>[],recents:()=>[],tabs:()=>[],activeTabKey:null,sideNavCollapsed:false,menuSearchOpen:false,operationCount:0,notificationCount:0,operationsOpen:false,notificationsOpen:false,homeActive:false,workspaceMaxTabs:10,shellNotice:null,themeMode:'light'})
const emit=defineEmits<{home:[];open:[entry:KbxNavigationResolvedEntry];openRecent:[entry:KbxRecentNavigation];selectTab:[tab:KbxWorkspaceTab];closeTab:[tab:KbxWorkspaceTab];toggleTabPin:[tab:KbxWorkspaceTab];toggleFavorite:[screenId:string];toggleSideNav:[];menuSearchOpen:[];menuSearchClose:[];operations:[];notifications:[];themeToggle:[];profile:[];dismissShellNotice:[]}>()

const moduleOptions=computed(()=>[...new Set(props.sections.map(section=>section.module).filter((module):module is NonNullable<KbxNavigationSection['module']>=>Boolean(module)))])
const focusedModule=ref(props.activeModule||moduleOptions.value[0]||'')
watch([()=>props.activeModule,moduleOptions],()=>{if(props.activeModule)focusedModule.value=props.activeModule;else if(!moduleOptions.value.includes(focusedModule.value as any))focusedModule.value=moduleOptions.value[0]??''},{immediate:true})
function selectModule(module:string){if(moduleOptions.value.includes(module as any))focusedModule.value=module}

const priorityScreenIds=computed(()=>[...props.favorites.map(x=>x.screenId),...props.recents.map(x=>x.screenId)].filter((id,index,list)=>list.indexOf(id)===index))
</script>

<template>
  <div class="app-shell" :data-kbx-module="focusedModule || 'COMMON'" :data-home-active="props.homeActive || undefined">
    <a class="skip-link" href="#kbx-main-workspace">본문 바로가기</a>
    <KbxGlobalHeader :product-name="props.productName" :active-module="focusedModule" :modules="moduleOptions" :operation-count="props.operationCount" :notification-count="props.notificationCount" :operations-open="props.operationsOpen" :notifications-open="props.notificationsOpen" :home-active="props.homeActive" :theme-mode="props.themeMode" @home="emit('home')" @module-select="selectModule" @menu-search="emit('menuSearchOpen')" @operations="emit('operations')" @notifications="emit('notifications')" @theme-toggle="emit('themeToggle')" @profile="emit('profile')" />
    <div class="below-header">
      <KbxSideNavigation :sections="props.sections" :favorites="props.favorites" :recents="props.recents" :active-screen-id="props.activeScreenId" :collapsed="props.sideNavCollapsed" :home-active="props.homeActive" :preferred-module="focusedModule" @home="emit('home')" @open="emit('open',$event)" @open-recent="emit('openRecent',$event)" @toggle-favorite="emit('toggleFavorite',$event)" @toggle-collapsed="emit('toggleSideNav')" @module-selected="selectModule" @menu-search="emit('menuSearchOpen')" />
      <main class="workspace">
        <KbxWorkspaceTabs :tabs="props.tabs" :active-key="props.activeTabKey" :max-tabs="props.workspaceMaxTabs" @select="emit('selectTab',$event)" @close-request="emit('closeTab',$event)" @toggle-pin="emit('toggleTabPin',$event)" />
        <aside v-if="props.shellNotice" class="shell-notice" role="status" aria-live="polite"><span>{{props.shellNotice}}</span><button type="button" aria-label="안내 닫기" @click="emit('dismissShellNotice')">×</button></aside>
        <section class="runtime"><slot name="runtime" /></section>
        <section id="kbx-main-workspace" class="content" tabindex="-1"><slot /></section>
      </main>
    </div>
    <KbxMenuSearch :open="props.menuSearchOpen" :entries="props.allEntries" :priority-screen-ids="priorityScreenIds" @close="emit('menuSearchClose')" @select="emit('open',$event)" />
  </div>
</template>

<style scoped>.skip-link{position:fixed;left:var(--kbx-space-2);top:calc(var(--kbx-control-lg) * -2);z-index:300;padding:var(--kbx-space-2) var(--kbx-space-3);background:var(--kbx-color-text);color:var(--kbx-color-surface);border-radius:var(--kbx-radius-sm)}.skip-link:focus{top:var(--kbx-space-2)}.app-shell{height:100vh;min-height:var(--kbx-app-shell-min-height);display:flex;flex-direction:column;background:var(--kbx-color-workspace);color:var(--kbx-color-text)}.below-header{flex:1;min-height:0;display:flex}.workspace{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--kbx-color-workspace)}.runtime{background:var(--kbx-color-surface)}.content{flex:1;min-height:0;overflow:auto;background:var(--kbx-color-workspace)}.shell-notice{min-height:var(--kbx-shell-notice-height);display:flex;align-items:center;justify-content:space-between;gap:var(--kbx-space-2);padding:0 var(--kbx-space-3);border-bottom:var(--kbx-border-width) solid var(--kbx-color-warning-border);background:var(--kbx-color-warning-surface);font-size:var(--kbx-font-sm)}.shell-notice button{width:var(--kbx-control-xs);height:var(--kbx-control-xs);border:0;background:transparent;color:var(--kbx-color-text-muted)}
</style>
