<template>
  <el-drawer
    v-if="modelValue"
    :model-value="modelValue"
    direction="rtl"
    size="620px"
    :close-on-click-modal="true"
    :before-close="drawerDirtyGuard.beforeClose"
    :show-close="false"
    class="precaution-editor-drawer"
    @update:model-value="emit('update:modelValue', $event)"
  >
    <template #header>
      <div class="editor-header">
        <div class="editor-title">{{ precautionId ? TEXT.modules.knowledgeNotes.editTitle : TEXT.modules.knowledgeNotes.newTitle }}</div>
      </div>
    </template>

    <el-form :model="form" label-position="top" class="precaution-editor-form">
      <div class="form-group">
        <div class="form-group-title">
          <span class="group-dot group-dot-basic"></span>
          {{ TEXT.modules.knowledgeNotes.title }}
        </div>
        <el-row :gutter="16">
          <el-col :span="12">
            <el-form-item :label="TEXT.common.fields.site" required>
              <el-select v-model="form.site_name" :disabled="isReadOnly" :placeholder="TEXT.common.placeholders.select" filterable class="full-width">
                <el-option
                  v-for="site in sites"
                  :key="site.id || site.name"
                  :label="site.name"
                  :value="site.name"
                  :disabled="site.is_active === false"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="TEXT.common.fields.level">
              <el-select v-model="form.level" :disabled="isReadOnly" :placeholder="TEXT.common.placeholders.select" clearable class="full-width">
                <el-option v-for="level in levelOptions" :key="level.value" :label="level.label" :value="level.value" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item :label="TEXT.common.fields.title" required>
          <el-input v-model="form.title" :disabled="isReadOnly" :placeholder="TEXT.common.placeholders.input + TEXT.common.fields.title" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.content" required>
          <el-input v-model="form.content" :disabled="isReadOnly" type="textarea" :rows="4" :placeholder="TEXT.common.placeholders.input" />
        </el-form-item>
      </div>

      <div class="form-group attachment-form-group">
        <div class="form-group-title">
          <span class="group-dot group-dot-attachment"></span>
          {{ TEXT.common.labels.attachments }}
        </div>
        <AttachmentList
          ref="attachmentPanelRef"
          :study-id="studyId"
          :entity-type="'precaution'"
          :entity-id="precautionId || ''"
          :mode="'upload'"
          :readonly="isReadOnly"
        />
      </div>
    </el-form>

    <template #footer>
      <div class="drawer-footer">
        <el-button @click="emit('update:modelValue', false)">{{ TEXT.common.actions.cancel }}</el-button>
        <el-button type="primary" :loading="saving" :disabled="isReadOnly" @click="submit">{{ TEXT.common.actions.save }}</el-button>
      </div>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
import { computed, reactive, ref, watch } from "vue";
import { ElMessage } from "element-plus";
import { createPrecaution, getPrecaution, updatePrecaution } from "../../api/precautions";
import { fetchSites } from "../../api/sites";
import { useStudyStore } from "../../store/study";
import { usePermission } from "../../utils/permission";
import { useDrawerDirtyGuard } from "../../utils/drawerDirtyGuard";
import AttachmentList from "../../components/attachments/AttachmentList.vue";
import { TEXT } from "../../locales";
import { precautionLevelOptions } from "./precautionOptions";

const props = defineProps<{ modelValue: boolean; precautionId?: string }>();
const emit = defineEmits<{
  (event: "update:modelValue", value: boolean): void;
  (event: "success", id: string): void;
}>();

const study = useStudyStore();
const { can } = usePermission();
const saving = ref(false);
const sites = ref<any[]>([]);
const levelOptions = precautionLevelOptions;
const studyId = computed(() => study.currentStudy?.id || "");
const isEdit = computed(() => !!props.precautionId);
const attachmentPanelRef = ref<InstanceType<typeof AttachmentList> | null>(null);

const form = reactive({
  site_name: "",
  title: "",
  level: "",
  content: "",
});

const siteActiveMap = computed(() => new Map(sites.value.map((site) => [site.name, !!site.is_active])));
const canCreatePrecaution = computed(() => can("precautions.create"));
const canUpdatePrecaution = computed(() => can("precautions.update"));
const canSavePrecaution = computed(() => (isEdit.value ? canUpdatePrecaution.value : canCreatePrecaution.value));
const isInactiveSite = computed(() => isEdit.value && !!form.site_name && siteActiveMap.value.get(form.site_name) === false);
const isReadOnly = computed(() => !canSavePrecaution.value || isInactiveSite.value);
const drawerDirtyGuard = useDrawerDirtyGuard(() => ({
  form,
  attachments: attachmentPanelRef.value?.pendingSnapshot() || [],
}));
const reset = () => {
  form.site_name = "";
  form.title = "";
  form.level = "";
  form.content = "";
};

const loadSites = async () => {
  if (!studyId.value) return;
  try {
    const { data } = await fetchSites(studyId.value, { limit: 500 });
    sites.value = Array.isArray(data) ? data : data.items || [];
  } catch {
    sites.value = [];
  }
};

const load = async () => {
  reset();
  await loadSites();
  if (!isEdit.value || !studyId.value || !props.precautionId) {
    drawerDirtyGuard.syncBaseline();
    return;
  }
  try {
    const { data } = await getPrecaution(studyId.value, props.precautionId);
    Object.assign(form, {
      site_name: data.site_name || "",
      title: data.title || "",
      level: data.level || "",
      content: data.content || "",
    });
    drawerDirtyGuard.syncBaseline();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.loadFailed);
  }
};

const submit = async () => {
  if (!studyId.value) return;
  if (!canSavePrecaution.value) {
    ElMessage.warning("权限不足");
    return;
  }
  if (isReadOnly.value || siteActiveMap.value.get(form.site_name) === false) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!form.site_name) {
    ElMessage.warning(TEXT.common.messages.required);
    return;
  }
  saving.value = true;
  try {
    const payload = {
      site_name: form.site_name,
      title: form.title,
      level: form.level || null,
      content: form.content,
    };
    let id = props.precautionId || "";
    if (props.precautionId) {
      await updatePrecaution(studyId.value, props.precautionId, payload);
    } else {
      const { data } = await createPrecaution(studyId.value, payload);
      id = data.id;
    }
    await attachmentPanelRef.value?.uploadPending(id);
    ElMessage.success(props.precautionId ? TEXT.common.messages.saveSuccess : TEXT.common.messages.createSuccess);
    drawerDirtyGuard.syncBaseline();
    emit("success", id);
    emit("update:modelValue", false);
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  } finally {
    saving.value = false;
  }
};

watch(
  () => [props.modelValue, props.precautionId, studyId.value] as const,
  ([visible]) => {
    if (visible) load();
  },
  { immediate: true }
);
</script>

<style scoped>
.editor-header {
  display: flex;
  align-items: center;
}

.editor-title {
  color: var(--ctms-text-main);
  font-size: 18px;
  font-weight: 700;
}

.precaution-editor-form {
  padding: 0 4px;
}

.form-group {
  padding: 16px 0;
}

.form-group-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  color: var(--ctms-text-main);
  font-size: 15px;
  font-weight: 700;
}

.group-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.group-dot-basic {
  background: var(--ctms-primary);
}

.group-dot-attachment {
  background: #22c55e;
}

.drawer-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.full-width {
  width: 100%;
}
</style>
