<script setup lang="ts">
import { computed, inject, ref } from 'vue'
import type { KbxCommandDefinition, KbxCommandGroup } from '@kbx/contracts'
import KbxButton from './KbxButton.vue'
import KbxConfirm from './KbxConfirm.vue'
import KbxExcelMenu from './KbxExcelMenu.vue'
import { KbxPermissionHostKey } from '../permission/host'

const props = withDefaults(defineProps<{ commands:KbxCommandDefinition[]; selectionCount?:number; status?:string; dirty?:boolean; can?:(permission:string)=>boolean }>(), { selectionCount:0, status:'', dirty:false })
const emit=defineEmits<{ command:[string] }>()
const pending=ref<KbxCommandDefinition|null>(null)
const permissionHost=inject(KbxPermissionHostKey,null)
function canPermission(permission:string){return props.can?props.can(permission):(permissionHost?.has(permission)??true)}
function invoke(command:KbxCommandDefinition){if(reason(command))return;if(command.confirm){pending.value=command;return}emit('command',command.id)}
function confirmPending(){const command=pending.value;if(!command)return;pending.value=null;emit('command',command.id)}
const groupOrder:KbxCommandGroup[]=['query','edit','workflow','output','more']
function effectivePermission(c:KbxCommandDefinition){return (props.status&&c.permissionByStatus?.[props.status])||c.permission}
function visible(c:KbxCommandDefinition){const permission=effectivePermission(c);return !permission||canPermission(permission)}
function reason(c:KbxCommandDefinition){
  const n=props.selectionCount
  if(c.requiresSelection&&n===0)return '처리할 항목을 선택하세요.'
  if(c.minSelection!=null&&n<c.minSelection)return `${c.minSelection}건 이상 선택하세요.`
  if(c.maxSelection!=null&&n>c.maxSelection)return `${c.maxSelection}건 이하로 선택하세요.`
  if(c.allowedStatuses?.length&&props.status&&!c.allowedStatuses.includes(props.status))return c.disabledReason??`현재 상태(${props.status})에서는 실행할 수 없습니다.`
  if(c.requiresDirty&&!props.dirty)return c.disabledReason??'변경된 내용이 없습니다.'
  if(c.requiresClean&&props.dirty)return c.disabledReason??'변경사항을 먼저 저장하세요.'
  return ''
}
const groups=computed(()=>groupOrder.map(group=>({group,commands:props.commands.filter(c=>c.group===group&&visible(c))})).filter(x=>x.commands.length))
</script>
<template><div class="kbx-command-bar" role="toolbar" aria-label="화면 명령"><template v-for="(item,index) in groups" :key="item.group"><div class="kbx-command-group" :data-group="item.group"><template v-for="command in item.commands" :key="command.id"><KbxExcelMenu v-if="command.menu==='excel'" :disabled="Boolean(reason(command))" :title="reason(command)||undefined" @export="emit('command',`${command.id}.export`)" @template="emit('command',`${command.id}.template`)" @import="emit('command',`${command.id}.import`)" @paste="emit('command',`${command.id}.paste`)" @history="emit('command',`${command.id}.history`)"/><KbxButton v-else :label="command.label" :shortcut="command.shortcut" :variant="command.variant" :disabled="Boolean(reason(command))" :title="reason(command)||undefined" @click="invoke(command)"/></template></div><span v-if="index<groups.length-1" class="kbx-command-separator" aria-hidden="true"/></template></div><KbxConfirm v-if="pending?.confirm" :open="Boolean(pending)" :title="pending.confirm.title" :detail="pending.confirm.detail" :level="pending.confirm.level" :confirm-label="pending.confirm.confirmLabel??pending.label" @update:open="value=>{if(!value)pending=null}" @confirm="confirmPending"/></template>
<style scoped>.kbx-command-bar{display:flex;align-items:center;gap:var(--kbx-space-2);min-height:var(--kbx-command-bar-height);overflow-x:auto}.kbx-command-group{display:flex;align-items:center;gap:var(--kbx-space-2);flex-shrink:0}.kbx-command-separator{width:var(--kbx-border-width);height:var(--kbx-command-separator-height);background:var(--kbx-color-border);flex-shrink:0}</style>
