<script setup lang="ts">
import { computed, inject } from 'vue'
import type { KbxScreenDefinition, KbxScreenTemplateCode, KbxScreenType } from '@kbx/contracts'
import KbxCommandBar from './KbxCommandBar.vue'
import KbxDataState from './KbxDataState.vue'
import KbxPageHeader from './KbxPageHeader.vue'
import { KbxScreenUtilityHostKey, type KbxScreenUtilityTab } from '../utility/host'
import { KbxPermissionHostKey } from '../permission/host'

const props = withDefaults(defineProps<{
  screen: KbxScreenDefinition
  /** Template wrapper must state the canonical screen type it implements. */
  expectedType?: KbxScreenType
  templateCode?: KbxScreenTemplateCode
  selectionCount?: number
  can?: (permission: string) => boolean
  breadcrumb?: string
  status?: string
  dirty?: boolean
  stickyCommands?: boolean
  commandBar?: boolean
  suppressDefaultUtility?: boolean
}>(), {
  expectedType: undefined,
  templateCode: undefined,
  selectionCount: 0,
  breadcrumb: '',
  status: '',
  dirty: false,
  stickyCommands: true,
  commandBar: true,
  suppressDefaultUtility: false,
})

const emit = defineEmits<{ command: [string] }>()
const utilityHost=inject(KbxScreenUtilityHostKey,null)
const permissionHost=inject(KbxPermissionHostKey,null)
const defaultUtilities=computed(()=>utilityHost?.available(props.screen)??[])
const utilityLabel:Record<KbxScreenUtilityTab,string>={help:'도움말',ai:'AI',suggestion:'제안'}
const templateMismatch=computed(()=>Boolean((props.expectedType&&props.screen.type!==props.expectedType)||(props.templateCode&&props.screen.templateCode!==props.templateCode)))
function canPermission(permission:string){return props.can?props.can(permission):(permissionHost?.has(permission)??true)}
const permissionDenied=computed(()=>Boolean(props.screen.permissions?.some(permission=>!canPermission(permission))))
</script>

<template>
  <section
    class="kbx-screen-frame"
    :data-screen-id="screen.id"
    :data-screen-type="screen.type"
    :data-template="templateCode"
    :data-status="status || undefined"
    :data-dirty="dirty || undefined"
    :data-access="permissionDenied?'denied':'allowed'"
  >
    <KbxPageHeader
      data-kbx-surface="page-header"
      :title="screen.title"
      :description="screen.description"
      :breadcrumb="breadcrumb"
      :status="status"
      :dirty="dirty"
    >
      <template #utility><slot name="utility" /><nav v-if="!suppressDefaultUtility && defaultUtilities.length" class="kbx-screen-frame__utility" aria-label="화면 보조기능"><button v-for="tab in defaultUtilities" :key="tab" type="button" @click="utilityHost?.open(screen,tab)">{{utilityLabel[tab]}}</button></nav></template>
    </KbxPageHeader>

    <KbxDataState v-if="templateMismatch" class="kbx-screen-frame__contract-error" state="error" title="화면 템플릿 구성이 올바르지 않습니다." detail="화면 정의와 표준 화면 유형이 일치하지 않습니다. 안전을 위해 업무 영역을 표시하지 않습니다." />
    <KbxDataState v-else-if="permissionDenied" class="kbx-screen-frame__contract-error" state="error" title="이 화면을 사용할 권한이 없습니다." detail="현재 권한으로는 이 업무 화면을 열 수 없습니다. 메뉴 검색에서 사용 가능한 업무를 선택하세요." />
    <template v-else>
      <div
        v-if="commandBar && ((screen.commands?.length ?? 0) > 0 || $slots.commands)"
        class="kbx-screen-frame__commands"
        data-kbx-surface="command-bar"
        :class="{ 'is-sticky': stickyCommands }"
      >
        <slot name="commands">
          <KbxCommandBar
            :commands="screen.commands ?? []"
            :selection-count="selectionCount"
            :status="status"
            :dirty="dirty"
            :can="canPermission"
            @command="emit('command', $event)"
          />
        </slot>
      </div>

      <div v-if="$slots.notice" class="kbx-screen-frame__notice"><slot name="notice" /></div>
      <div class="kbx-screen-frame__body"><slot /></div>
    </template>
  </section>
</template>

<style scoped>
.kbx-screen-frame {display:flex;flex-direction:column;min-height:0;height:100%;background:var(--kbx-color-surface)}
.kbx-screen-frame__commands{min-height:var(--kbx-command-bar-height);padding:0 var(--kbx-screen-inline-padding);border-bottom:var(--kbx-border-width) solid var(--kbx-color-border);background:var(--kbx-color-surface);z-index:8}
.kbx-screen-frame__commands.is-sticky{position:sticky;top:0}.kbx-screen-frame__notice{padding:var(--kbx-space-2) var(--kbx-screen-inline-padding) 0}.kbx-screen-frame__body{min-height:0;flex:1;display:flex;flex-direction:column;gap:var(--kbx-screen-section-gap);padding:var(--kbx-space-2) var(--kbx-screen-inline-padding) var(--kbx-space-3)}
.kbx-screen-frame__utility{display:flex;align-items:center;gap:var(--kbx-space-1)}.kbx-screen-frame__utility button{height:var(--kbx-control-xs);padding:0 var(--kbx-space-2);border:var(--kbx-border-width) solid var(--kbx-color-border);border-radius:var(--kbx-radius-sm);background:var(--kbx-color-surface);color:var(--kbx-color-text);font-size:var(--kbx-font-xs)}.kbx-screen-frame__utility button:hover{background:var(--kbx-color-surface-hover);border-color:var(--kbx-color-border-strong)}.kbx-screen-frame__contract-error{margin:var(--kbx-space-3) var(--kbx-screen-inline-padding)}
</style>
