<script setup lang="ts">
import ConfirmDialog from '@/components/maint/CommonConfirmDialog.vue'
import MntDialogCard from '@/components/maint/MntDialogCard.vue'
import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue'
import ItemFormFieldGroup from '@/components/items/ItemFormFieldGroup.vue'
import type {
  SaveSummaryItem,
  StudentFormState,
} from '@/composables/maint/useStudentMaintenanceForm'

interface FieldErrorItem {
  field: string
  message: string
}

interface GradeOption {
  title: string
  value: number
}

defineProps<{
  confirmCloseVisible: boolean
  confirmDeleteVisible: boolean
  confirmNavigateVisible: boolean
  confirmSaveVisible: boolean
  confirmSwitchVisible: boolean
  departments: string[]
  dialogSubtitle: string
  dialogTitle: string
  dialogVisible: boolean
  enrollYears: number[]
  errorSummary: FieldErrorItem[]
  fieldErrors: Record<keyof StudentFormState, string[]>
  gradeOptions: GradeOption[]
  hasNextRecord: boolean
  hasPrevRecord: boolean
  isDirty: boolean
  isEditMode: boolean
  isFormLocked: boolean
  isFormReadonly: boolean
  isLoading: boolean
  isSaving: boolean
  isViewMode: boolean
  pendingDeleteLabel: string
  saveSummary: SaveSummaryItem[]
  statuses: string[]
}>()

const form = defineModel<StudentFormState>('form', { required: true })

const emit = defineEmits<{
  (e: 'update:confirmCloseVisible', value: boolean): void
  (e: 'update:confirmDeleteVisible', value: boolean): void
  (e: 'update:confirmNavigateVisible', value: boolean): void
  (e: 'update:confirmSaveVisible', value: boolean): void
  (e: 'update:confirmSwitchVisible', value: boolean): void
  (e: 'dialog-visible-change', value: boolean): void
  (e: 'clear-field-error', field: keyof StudentFormState): void
  (e: 'close'): void
  (e: 'confirm-close'): void
  (e: 'confirm-delete'): void
  (e: 'confirm-navigate'): void
  (e: 'confirm-save'): void
  (e: 'confirm-switch'): void
  (e: 'delete-current'): void
  (e: 'first'): void
  (e: 'last'): void
  (e: 'next'): void
  (e: 'prev'): void
  (e: 'save'): void
  (e: 'scroll-to-field', field: string): void
  (e: 'switch-to-edit'): void
  (e: 'switch-to-view'): void
}>()
</script>

<template>
  <teleport to="body">
    <v-overlay
      class="dialog-overlay"
      :close-on-content-click="false"
      :model-value="dialogVisible"
      scrim="rgba(0, 0, 0, 0.45)"
      scroll-strategy="block"
      @update:model-value="emit('dialog-visible-change', $event)"
    >
      <div class="dialog-panel">
        <MntDialogCard
          content-class="pa-2 flex-grow-1 overflow-y-auto"
          :dialog-subtitle="dialogSubtitle"
          :dialog-title="dialogTitle"
          :is-edit-mode="isEditMode"
          :is-view-mode="isViewMode"
          width="100%"
        >
          <template #toolbar>
            <MntRecordNavToolbar
              edit-label="進入編輯"
              first-label="第一筆"
              :has-next-record="hasNextRecord"
              :has-prev-record="hasPrevRecord"
              :is-edit-mode="isEditMode"
              :is-view-mode="isViewMode"
              last-label="最後一筆"
              view-label="回到檢視"
              @first="emit('first')"
              @last="emit('last')"
              @next="emit('next')"
              @prev="emit('prev')"
              @switch-to-edit="emit('switch-to-edit')"
              @switch-to-view="emit('switch-to-view')"
            />
          </template>
          <template #content>
            <v-alert
              v-if="errorSummary.length > 0 && !isLoading"
              class="mb-4"
              type="error"
              variant="tonal"
            >
              <div class="text-subtitle-2 mb-2">請先修正以下問題</div>
              <div class="d-flex flex-column ga-1">
                <v-btn
                  v-for="error in errorSummary"
                  :key="error.field"
                  color="error"
                  size="small"
                  variant="text"
                  @click="emit('scroll-to-field', error.field)"
                >
                  {{ error.message }}
                </v-btn>
              </div>
            </v-alert>

            <v-skeleton-loader
              v-if="isLoading"
              class="mt-4"
              type="subtitle,paragraph"
              width="100%"
            />

            <v-form
              v-else
              :class="{ 'form-readonly': isFormReadonly }"
              @submit.prevent="emit('save')"
            >
              <ItemFormFieldGroup
                v-model="form"
                :departments="departments"
                :enroll-years="enrollYears"
                :field-errors="fieldErrors"
                :grade-options="gradeOptions"
                :is-form-locked="isFormLocked"
                :is-form-readonly="isFormReadonly"
                :statuses="statuses"
                @clear-field-error="emit('clear-field-error', $event)"
              />
            </v-form>
          </template>
          <template #actions>
            <v-spacer />
            <v-btn :disabled="isSaving" variant="text" @click="emit('close')">取消</v-btn>
            <v-btn
              v-if="isEditMode"
              color="error"
              :disabled="isSaving"
              variant="tonal"
              @click="emit('delete-current')"
            >
              刪除
            </v-btn>
            <v-btn
              v-if="!isViewMode"
              color="primary"
              :disabled="!isDirty || isLoading"
              :loading="isSaving"
              variant="flat"
              @click="emit('save')"
            >
              儲存
            </v-btn>
            <v-btn v-else color="primary" variant="flat" @click="emit('close')">關閉</v-btn>
          </template>
        </MntDialogCard>
      </div>
    </v-overlay>
  </teleport>

  <ConfirmDialog
    :model-value="confirmCloseVisible"
    confirm-color="error"
    confirm-text="關閉不儲存"
    message="目前有尚未儲存的內容，確定要關閉嗎？"
    title="未儲存變更"
    @confirm="emit('confirm-close')"
    @update:model-value="emit('update:confirmCloseVisible', $event)"
  />

  <ConfirmDialog
    :model-value="confirmSaveVisible"
    :confirm-loading="isSaving"
    confirm-text="確認儲存"
    max-width="520"
    title="確認儲存變更"
    @confirm="emit('confirm-save')"
    @update:model-value="emit('update:confirmSaveVisible', $event)"
  >
    <div v-if="saveSummary.length > 0" class="d-flex flex-column ga-2">
      <div v-for="item in saveSummary" :key="item.label" class="d-flex flex-column">
        <div class="text-caption text-medium-emphasis">{{ item.label }}</div>
        <div v-if="item.before !== null" class="text-body-2">
          <span class="text-medium-emphasis">原：</span>
          <span :class="{ 'text-medium-emphasis': item.before === '—' }">
            {{ item.before }}
          </span>
        </div>
        <div class="text-body-2">
          <span class="text-medium-emphasis">新：</span>
          <span :class="{ 'text-medium-emphasis': item.after === '—' }">
            {{ item.after }}
          </span>
        </div>
      </div>
    </div>
    <div v-else class="text-body-2">目前沒有可儲存的變更。</div>
  </ConfirmDialog>

  <ConfirmDialog
    :model-value="confirmDeleteVisible"
    confirm-color="error"
    confirm-text="確定刪除"
    :message="`確定要刪除 ${pendingDeleteLabel} 嗎？此操作無法復原。`"
    title="確認刪除"
    @confirm="emit('confirm-delete')"
    @update:model-value="emit('update:confirmDeleteVisible', $event)"
  />

  <ConfirmDialog
    :model-value="confirmSwitchVisible"
    confirm-text="確定切換"
    max-width="480"
    message="目前有尚未儲存的內容，切換為檢視模式將會捨棄變更，確定要切換嗎？"
    title="未儲存變更"
    @confirm="emit('confirm-switch')"
    @update:model-value="emit('update:confirmSwitchVisible', $event)"
  />

  <ConfirmDialog
    :model-value="confirmNavigateVisible"
    confirm-text="確定切換"
    max-width="480"
    message="目前有尚未儲存的內容，切換到其他資料將會捨棄變更，確定要切換嗎？"
    title="未儲存變更"
    @confirm="emit('confirm-navigate')"
    @update:model-value="emit('update:confirmNavigateVisible', $event)"
  />
</template>

<style scoped>
.dialog-overlay :deep(.v-overlay__content) {
  height: 100vh;
  display: flex;
  justify-content: flex-end;
  width: 100vw;
  max-width: 100vw;
}

.dialog-panel {
  width: 760px;
  max-width: 100%;
  height: 100vh;
  background: rgb(var(--v-theme-surface));
  padding: 12px;
  box-shadow: -12px 0 24px rgba(0, 0, 0, 0.18);
  display: flex;
}

.form-readonly :deep(.v-field) {
  pointer-events: none;
}
</style>
