<script lang="ts" setup>
/**
 * 排班格子右键快捷菜单（月历视图 / 矩阵总览共用）
 * 参照工作台日历 CalendarPanel 的右键菜单模式：Teleport body + fixed 定位 +
 * 贴边收缩 + 点击/滚动关闭 + 毛玻璃样式；菜单项按排班动作定制。
 * 组件只负责「展示与发出动作」，动作落地（调 save-days）由父组件完成，
 * 这样月历（单医生多日期）与矩阵（多医生多日期）可以共用同一菜单。
 */
import type { ShiftTemplate } from '../../api/schedule';

import { onMounted, onUnmounted, reactive, ref } from 'vue';

import { Icon } from '#/components/icon';

const props = defineProps<{
  /** 剪贴板是否有可粘贴的排班（父组件内存快照） */
  canPaste: boolean;
  /** 粘贴项摘要（如「上午 20号 / 下午 15号」），提示粘贴内容 */
  pasteSummary: string;
  /** 启用中的班次模板（内联子列表数据源） */
  templates: ShiftTemplate[];
}>();

const emit = defineEmits<{
  /** 动作统一出口：父组件根据当前选区执行 */
  action: [
    type: 'add_doctors' | 'apply_template' | 'clear' | 'copy' | 'custom' | 'paste' | 'rest',
    payload?: { templateId?: number },
  ];
}>();

/** 菜单状态：位置 + 标题 + 右键格子是否可复制 */
const state = reactive({
  visible: false,
  x: 0,
  y: 0,
  /** 标题文本（如「8月19日 · 已选 3 天」），由打开方组装 */
  title: '',
  /** 右键目标格子是否有可复制的时段（休诊/不出诊格禁用复制） */
  copyEnabled: false,
  /** 是否显示「添加医生排班」（月历视图才有意义；矩阵格已含医生维度、锁定医生入口无选人场景） */
  addDoctorsEnabled: false,
});

/** 「套用班次模板」内联子列表展开态（每次打开菜单重置收起） */
const templatesOpen = ref(false);

/**
 * 打开右键菜单：贴边时向内收缩，避免菜单溢出视口
 * 估算高度 330（含模板子列表收起态），宽 210
 */
function open(
  e: MouseEvent,
  meta: { addDoctorsEnabled?: boolean; copyEnabled: boolean; title: string },
) {
  state.title = meta.title;
  state.copyEnabled = meta.copyEnabled;
  state.addDoctorsEnabled = Boolean(meta.addDoctorsEnabled);
  // 贴边收缩 + 下限保护：小视口时也不让菜单跑出屏幕左上角
  state.x = Math.max(8, Math.min(e.clientX, window.innerWidth - 220));
  state.y = Math.max(8, Math.min(e.clientY, window.innerHeight - 340));
  templatesOpen.value = false;
  state.visible = true;
}

function close() {
  state.visible = false;
}

/** 发出动作并关闭菜单 */
function fire(
  type: 'add_doctors' | 'apply_template' | 'clear' | 'copy' | 'custom' | 'paste' | 'rest',
  payload?: { templateId?: number },
) {
  emit('action', type, payload);
  close();
}

/** 点击任意处 / 滚动时关闭（capture 阶段监听滚动，覆盖弹窗内部滚动容器） */
onMounted(() => {
  window.addEventListener('click', close);
  window.addEventListener('scroll', close, true);
  window.addEventListener('resize', close);
});
onUnmounted(() => {
  window.removeEventListener('click', close);
  window.removeEventListener('scroll', close, true);
  window.removeEventListener('resize', close);
});

defineExpose({ open, close });
</script>

<template>
  <Teleport to="body">
    <div
      v-if="state.visible"
      class="sched-ctx"
      :style="{ left: `${state.x}px`, top: `${state.y}px` }"
      @click.stop
      @contextmenu.prevent
    >
      <div class="sched-ctx__title">{{ state.title }}</div>
      <!-- 套用班次模板：点击内联展开模板子列表（避免自实现 hover 子菜单的复杂度） -->
      <div class="sched-ctx__item" @click="templatesOpen = !templatesOpen">
        <span class="sched-ctx__label">
          <Icon icon="lucide:layers" />
          套用班次模板
        </span>
        <Icon :icon="templatesOpen ? 'lucide:chevron-down' : 'lucide:chevron-right'" />
      </div>
      <div v-if="templatesOpen" class="sched-ctx__sub">
        <div
          v-for="tpl in props.templates"
          :key="tpl.id"
          class="sched-ctx__item sched-ctx__item--sub"
          @click="fire('apply_template', { templateId: tpl.id })"
        >
          <span class="sched-ctx__label">{{ tpl.name }}</span>
          <span class="sched-ctx__hint">
            {{ tpl.slots.reduce((sum, s) => sum + Number(s.capacity || 0), 0) }}号
          </span>
        </div>
        <div v-if="props.templates.length === 0" class="sched-ctx__empty">
          暂无启用模板
        </div>
      </div>
      <div class="sched-ctx__item" @click="fire('custom')">
        <span class="sched-ctx__label">
          <Icon icon="lucide:clock" />
          自定义时段…
        </span>
      </div>
      <!-- 添加医生排班：选医生 + 选模板/自定义时段，一步给多位医生排当天班 -->
      <div
        v-if="state.addDoctorsEnabled"
        class="sched-ctx__item"
        @click="fire('add_doctors')"
      >
        <span class="sched-ctx__label">
          <Icon icon="lucide:user-plus" />
          添加医生排班…
        </span>
      </div>
      <div class="sched-ctx__divider"></div>
      <div
        class="sched-ctx__item"
        :class="{ 'sched-ctx__item--disabled': !state.copyEnabled }"
        @click="state.copyEnabled && fire('copy')"
      >
        <span class="sched-ctx__label">
          <Icon icon="lucide:copy" />
          复制该日排班
        </span>
      </div>
      <div
        class="sched-ctx__item"
        :class="{ 'sched-ctx__item--disabled': !props.canPaste }"
        @click="props.canPaste && fire('paste')"
      >
        <span class="sched-ctx__label">
          <Icon icon="lucide:clipboard-paste" />
          粘贴排班
        </span>
        <span v-if="props.canPaste" class="sched-ctx__hint">{{ props.pasteSummary }}</span>
      </div>
      <div class="sched-ctx__divider"></div>
      <div class="sched-ctx__item sched-ctx__item--danger" @click="fire('rest')">
        <span class="sched-ctx__label">
          <Icon icon="lucide:ban" />
          设为休诊
        </span>
      </div>
      <div class="sched-ctx__item" @click="fire('clear')">
        <span class="sched-ctx__label">
          <Icon icon="lucide:rotate-ccw" />
          恢复默认规则
        </span>
      </div>
    </div>
  </Teleport>
</template>

<style scoped>
/* 毛玻璃浮层：与工作台日历右键菜单同一设计语言 */
.sched-ctx {
  position: fixed;
  z-index: 2100;
  min-width: 200px;
  max-width: 260px;
  padding: 6px;
  background: hsl(var(--popover, var(--background)) / 82%);
  border: 1px solid hsl(var(--border) / 60%);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgb(0 0 0 / 16%);
  backdrop-filter: blur(18px) saturate(160%);
}

.sched-ctx__title {
  padding: 4px 10px 6px;
  overflow: hidden;
  font-size: 12px;
  color: hsl(var(--muted-foreground));
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px solid hsl(var(--border));
}

.sched-ctx__item {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: space-between;
  padding: 7px 10px;
  margin-top: 2px;
  font-size: 13px;
  color: hsl(var(--foreground));
  cursor: pointer;
  border-radius: 6px;
  transition: background 0.12s;
}

.sched-ctx__item:hover {
  background: hsl(var(--primary) / 0.08);
}

.sched-ctx__item--sub {
  padding-left: 26px;
}

.sched-ctx__item--danger {
  color: hsl(var(--destructive));
}

.sched-ctx__item--danger:hover {
  background: hsl(var(--destructive) / 0.08);
}

.sched-ctx__item--disabled {
  color: hsl(var(--muted-foreground) / 0.55);
  cursor: not-allowed;
}

.sched-ctx__item--disabled:hover {
  background: none;
}

.sched-ctx__label {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sched-ctx__hint {
  flex-shrink: 0;
  max-width: 90px;
  overflow: hidden;
  font-size: 11px;
  color: hsl(var(--muted-foreground));
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 模板子列表：限高滚动，防模板多时菜单超出视口 */
.sched-ctx__sub {
  max-height: 150px;
  overflow-y: auto;
}

.sched-ctx__empty {
  padding: 6px 10px 6px 26px;
  font-size: 12px;
  color: hsl(var(--muted-foreground) / 0.7);
}

.sched-ctx__divider {
  height: 1px;
  margin: 4px 6px;
  background: hsl(var(--border) / 70%);
}
</style>
