<script setup lang="ts">
// 일정 생성/수정 모달
import { computed, ref, watch } from 'vue'
import BaseModal from '@/components/common/BaseModal.vue'
import UserAvatar from '@/components/UserAvatar.vue'
import type {
  ApiScheduleCategory,
  ApiScheduleEvent,
  ApiSchedulePerson,
  ScheduleEventPayload,
} from '@/types/schedule'

const props = defineProps<{
  categories: ApiScheduleCategory[]
  people: ApiSchedulePerson[]
  init: ApiScheduleEvent | null
  defaultDate: string
}>()
const emit = defineEmits<{
  (e: 'save', payload: ScheduleEventPayload): void
  (e: 'close'): void
}>()

const isEdit = computed(() => !!props.init)

// init.time → 시작/종료 HH:MM 파싱
function parseTime(tm: string): { start: string; end: string } {
  if (/\d/.test(tm) && (tm.includes('–') || tm.includes('-'))) {
    const parts = tm.split(/[–-]/).map((s) => s.trim())
    const a = parts[0] ?? ''
    const b = parts[1] ?? ''
    return {
      start: /^\d{1,2}:\d{2}/.test(a) ? a : '09:00',
      end: /^\d{1,2}:\d{2}/.test(b) ? b : '',
    }
  }
  if (/^\d{1,2}:\d{2}/.test(tm)) return { start: tm.trim(), end: '' }
  return { start: '09:00', end: '10:00' }
}

const i = props.init
const pt = parseTime(i?.time ?? '')
const ordered = computed(() =>
  [...props.categories].sort((a, b) => a.sortOrder - b.sortOrder),
)

const title = ref(i?.title ?? '')
const categoryId = ref(i?.categoryId ?? ordered.value[0]?.id ?? '')
const s = ref(i?.start ?? props.defaultDate)
const e = ref(i?.end ?? i?.start ?? props.defaultDate)
const startT = ref(pt.start)
const endT = ref(pt.end)
const place = ref(i?.place && i.place !== '—' ? i.place : '')
const desc = ref(i?.description ?? '')
const allHands = ref(i?.allHands ?? false)
const attendeeIds = ref<string[]>(i?.attendees.map((a) => a.id) ?? [])

// 시작일 변경 시 종료일이 더 빠르면 맞춰줌
watch(s, (v) => {
  if (e.value < v) e.value = v
})

const valid = computed(
  () =>
    !!title.value.trim() &&
    !!categoryId.value &&
    !!s.value &&
    !!e.value &&
    e.value >= s.value &&
    !!startT.value,
)

// 참석자 — 검색 입력 + 후보 드롭다운 + 선택 칩 (업무 생성의 담당자 등록과 동일 방식)
const attendeeQuery = ref('')
const showAttendeeDropdown = ref(false)
// 선택된 참석자(칩 표시용)
const selectedAttendees = computed(() =>
  attendeeIds.value
    .map((id) => props.people.find((p) => p.id === id))
    .filter((p): p is ApiSchedulePerson => !!p),
)
// 후보 = 미선택 사용자, 이름 검색 필터
const attendeeCandidates = computed(() => {
  const selected = new Set(attendeeIds.value)
  const kw = attendeeQuery.value.trim()
  return props.people
    .filter((p) => !selected.has(p.id))
    .filter((p) => !kw || p.name.includes(kw))
})
function addAttendee(id: string): void {
  allHands.value = false
  if (!attendeeIds.value.includes(id)) {
    attendeeIds.value = [...attendeeIds.value, id]
  }
  attendeeQuery.value = ''
}
function removeAttendee(id: string): void {
  attendeeIds.value = attendeeIds.value.filter((x) => x !== id)
}
function selectAllHands(): void {
  allHands.value = true
  attendeeIds.value = []
  attendeeQuery.value = ''
  showAttendeeDropdown.value = false
}
function clearAllHands(): void {
  allHands.value = false
}
function onAttendeeBlur(): void {
  // 항목은 @mousedown.prevent 로 선택하므로 약간 지연 후 닫는다
  setTimeout(() => (showAttendeeDropdown.value = false), 120)
}

function submit(): void {
  if (!valid.value) return
  const time = endT.value ? `${startT.value} – ${endT.value}` : startT.value
  emit('save', {
    title: title.value.trim(),
    categoryId: categoryId.value,
    start: s.value,
    end: e.value,
    time,
    place: place.value.trim(),
    description: desc.value.trim(),
    allHands: allHands.value,
    attendeeIds: allHands.value ? [] : attendeeIds.value,
  })
}
</script>

<template>
  <BaseModal
    :title="isEdit ? '일정 수정' : '새 일정'"
    @close="emit('close')"
  >
    <label class="form-field"><span class="form-label">제목</span>
      <input
        v-model="title"
        class="form-input"
        placeholder="일정 제목을 입력하세요"
        autofocus
      >
    </label>
    <label class="form-field"><span class="form-label">유형</span>
      <div class="form-select-wrap">
        <select
          v-model="categoryId"
          class="form-select"
        >
          <option
            v-for="c in ordered"
            :key="c.id"
            :value="c.id"
          >
            {{ c.label }}
          </option>
        </select>
        <span class="form-select-chev">
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          ><path d="m6 9 6 6 6-6" /></svg>
        </span>
      </div>
    </label>
    <div class="form-row">
      <label class="form-field"><span class="form-label">시작일</span>
        <input
          v-model="s"
          type="date"
          class="form-input"
        >
      </label>
      <label class="form-field"><span class="form-label">종료일</span>
        <input
          v-model="e"
          type="date"
          class="form-input"
          :min="s"
        >
      </label>
    </div>
    <div class="form-field">
      <span class="form-label">시간</span>
      <div class="time-row">
        <input
          v-model="startT"
          type="time"
          class="form-input time-input"
        >
        <span class="time-dash">–</span>
        <input
          v-model="endT"
          type="time"
          class="form-input time-input"
        >
      </div>
    </div>
    <label class="form-field"><span class="form-label">장소</span>
      <input
        v-model="place"
        class="form-input"
        placeholder="장소를 입력하세요"
      >
    </label>
    <div class="form-field">
      <span class="form-label">참석자</span>
      <div class="combo">
        <div class="combo-field">
          <input
            v-model="attendeeQuery"
            class="combo-input"
            placeholder="참석자를 검색하세요"
            autocomplete="off"
            @focus="showAttendeeDropdown = true"
            @blur="onAttendeeBlur"
          >
          <span class="combo-caret">
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            ><path d="m6 9 6 6 6-6" /></svg>
          </span>
        </div>
        <!-- 참석자 후보 드롭다운 -->
        <div
          v-if="showAttendeeDropdown"
          class="assignee-dd"
        >
          <!-- 전 직원(전체 대상) -->
          <button
            v-if="!allHands && !attendeeQuery.trim()"
            type="button"
            class="assignee-dd-item"
            @mousedown.prevent="selectAllHands"
          >
            <span class="ad-all">전</span>
            <span class="ad-nm">전 직원</span>
          </button>
          <button
            v-for="p in attendeeCandidates"
            :key="p.id"
            type="button"
            class="assignee-dd-item"
            @mousedown.prevent="addAttendee(p.id)"
          >
            <span class="avatar"><UserAvatar
              :url="p.avatarUrl"
              :name="p.name"
            /></span>
            <span class="ad-nm">{{ p.name }}</span>
          </button>
          <div
            v-if="attendeeCandidates.length === 0 && (allHands || attendeeQuery.trim())"
            class="assignee-dd-msg"
          >
            {{ people.length === 0 ? '등록된 사용자가 없습니다.' : '추가할 사용자가 없습니다.' }}
          </div>
        </div>
      </div>
      <!-- 선택된 참석자 칩 -->
      <div
        v-if="allHands || selectedAttendees.length"
        class="assignee-chips"
      >
        <span
          v-if="allHands"
          class="chip"
        >
          <span class="ad-all sm">전</span>전 직원
          <span
            class="x"
            @click="clearAllHands"
          >×</span>
        </span>
        <template v-else>
          <span
            v-for="p in selectedAttendees"
            :key="p.id"
            class="chip"
          >
            <span class="avatar"><UserAvatar
              :url="p.avatarUrl"
              :name="p.name"
            /></span>
            {{ p.name }}
            <span
              class="x"
              @click="removeAttendee(p.id)"
            >×</span>
          </span>
        </template>
      </div>
    </div>
    <label class="form-field"><span class="form-label">설명</span>
      <textarea
        v-model="desc"
        class="form-input form-textarea"
        placeholder="일정에 대한 메모를 입력하세요 (선택)"
        rows="3"
      />
    </label>

    <template #foot>
      <button
        class="mbtn"
        @click="emit('close')"
      >
        취소
      </button>
      <button
        class="mbtn primary"
        :disabled="!valid"
        @click="submit"
      >
        {{ isEdit ? '저장' : '추가' }}
      </button>
    </template>
  </BaseModal>
</template>

<style scoped>
/* 시간 입력 행 */
.time-row {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}
.time-input {
  width: auto;
  flex: 1;
  min-width: 0;
}
.time-dash {
  color: var(--text-3);
}

/* 참석자 — 업무 생성의 담당자 등록과 동일한 콤보(검색 입력 + 후보 드롭다운 + 선택 칩) */
.combo {
  position: relative;
}
.combo-field {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  padding: 0.4375rem 0.5rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: #fff;
}
.combo-field:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-weak);
}
.combo-input {
  flex: 1;
  min-width: 4.375rem;
  border: none;
  outline: none;
  font-family: inherit;
  font-size: 0.8125rem;
  padding: 0.25rem 0.125rem;
  background: transparent;
  color: var(--text);
}
.combo-input::placeholder {
  color: var(--text-3);
}
.combo-caret {
  color: var(--text-3);
  display: grid;
  place-items: center;
  margin-left: auto;
  flex-shrink: 0;
}
.combo-caret svg {
  width: 1rem;
  height: 1rem;
}
.assignee-dd {
  position: absolute;
  top: calc(100% + 0.375rem);
  left: 0;
  right: 0;
  z-index: 10;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 0.5625rem;
  box-shadow: var(--shadow-pop);
  padding: 0.375rem;
  max-height: 14rem;
  overflow-y: auto;
}
.assignee-dd-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.4375rem 0.5rem;
  border: none;
  background: transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.assignee-dd-item:hover {
  background: #f5f6f8;
}
.assignee-dd-item .avatar {
  width: 1.5rem;
  height: 1.5rem;
  flex-shrink: 0;
}
.ad-nm {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.assignee-dd-msg {
  padding: 0.625rem 0.5rem;
  font-size: 0.75rem;
  color: var(--text-3);
  text-align: center;
}
.assignee-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 0.5rem;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  background: #f1f2f4;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 0.1875rem 0.5rem 0.1875rem 0.1875rem;
  font-size: 0.781rem;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.chip .avatar {
  width: 1.375rem;
  height: 1.375rem;
  flex-shrink: 0;
}
.chip .x {
  color: var(--text-3);
  cursor: pointer;
  font-size: 0.8125rem;
  line-height: 1;
  margin-left: 0.0625rem;
}
.chip .x:hover {
  color: var(--red);
}
/* 전 직원 표식(드롭다운/칩 공용) */
.ad-all {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 0.6875rem;
  font-weight: 700;
  color: #fff;
  background: #9298a3;
  flex-shrink: 0;
}
.ad-all.sm {
  width: 1.375rem;
  height: 1.375rem;
  font-size: 0.625rem;
}
</style>
