<template>
  <div class="admin--field-list">
    <!-- 상단 액션 영역 -->
    <div class="admin--search-box">
      <div class="admin--search-actions">
        <button
          v-if="hasChanges"
          class="admin--btn-small admin--btn-small-secondary"
          :disabled="isSaving"
          @click="cancelAll"
        >
          모두 취소
        </button>
        <button
          class="admin--btn-small admin--btn-small-secondary"
          :disabled="selectedIds.length === 0"
          @click="bulkDelete"
        >
          선택 삭제<span v-if="selectedIds.length"> ({{ selectedIds.length }})</span>
        </button>
        <button class="admin--btn-small admin--btn-small-primary" @click="addNewRow">+ 구분 추가</button>
        <button
          v-if="hasChanges || isSaving"
          class="admin--btn-small admin--btn-small-danger"
          :disabled="isSaving"
          @click="bulkSave"
        >
          {{ isSaving ? "저장 중..." : `일괄 저장 (${changeCount})` }}
        </button>
      </div>
    </div>

    <!-- 테이블 -->
    <div class="admin--table-wrapper">
      <table class="admin--table">
        <thead>
          <tr>
            <th style="width: 80px;">
              <div class="input--wrap">
                <input
                  type="checkbox"
                  :checked="isAllSelected"
                  :indeterminate.prop="isPartialSelected"
                  @change="toggleAll($event.target.checked)"
                  aria-label="전체 선택"
                />
              </div>
            </th>
            <th style="">구분명</th>
            <th style="width: 20%;">정렬순서</th>
            <th style="width: 10%;">상태</th>
            <th style="width: 10%">등록일</th>
            <th style="width: 10%">관리</th>
          </tr>
        </thead>
        <tbody>
          <!-- 신규 행들 (테이블 상단) -->
          <tr v-for="n in newRows" :key="'new-' + n._tempId" class="admin--table-row-new">
            <td></td>
            <td @click.stop>
              <input
                v-model="n.name"
                type="text"
                class="admin--form-input admin--inline-input"
                placeholder="구분명 입력"
                @keyup.enter="bulkSave"
              />
            </td>
            <td @click.stop>
              <input
                v-model.number="n.sort_order"
                type="number"
                min="0"
                class="admin--form-input admin--inline-input"
                @keyup.enter="bulkSave"
              />
            </td>
            <td @click.stop>
              <select v-model="n.status_YN" class="admin--form-select admin--inline-input">
                <option value="Y">사용중</option>
                <option value="N">미사용</option>
              </select>
            </td>
            <td class="date">{{ todayLabel }}</td>
            <td @click.stop>
              <button class="admin--btn-small admin--btn-small-secondary" @click="removeNewRow(n._tempId)">제거</button>
            </td>
          </tr>

          <tr v-if="isLoading">
            <td colspan="6" class="admin--table-loading">데이터를 불러오는 중...</td>
          </tr>
          <tr v-else-if="!displayedItems || displayedItems.length === 0">
            <td colspan="6" class="admin--table-empty" v-if="newRows.length === 0">등록된 어종구분이 없습니다.</td>
          </tr>
          <tr
            v-else
            v-for="item in displayedItems"
            :key="item.id"
            :class="{
              'admin--table-row-new': editing[item.id],
              'admin--table-row-clickable': !editing[item.id],
            }"
            @click="!editing[item.id] && startEdit(item)"
          >
            <td @click.stop>
              <div class="input--wrap">
                <input
                  type="checkbox"
                  :value="item.id"
                  v-model="selectedIds"
                />
              </div>
            </td>

            <!-- 수정 모드 -->
            <template v-if="editing[item.id]">
              <td @click.stop>
                <input
                  v-model="editing[item.id].name"
                  type="text"
                  class="admin--form-input admin--inline-input"
                  @keyup.enter="bulkSave"
                />
              </td>
              <td @click.stop>
                <input
                  v-model.number="editing[item.id].sort_order"
                  type="number"
                  min="0"
                  class="admin--form-input admin--inline-input center"
                  @keyup.enter="bulkSave"
                />
              </td>
              <td @click.stop>
                <select v-model="editing[item.id].status_YN" class="admin--form-select admin--inline-input">
                  <option value="Y">사용중</option>
                  <option value="N">미사용</option>
                </select>
              </td>
              <td class="date">{{ formatDate(item.created_at) }}</td>
              <td @click.stop>
                <button class="admin--btn-small admin--btn-small-secondary" @click="cancelEdit(item.id)">취소</button>
              </td>
            </template>

            <!-- 일반 모드 -->
            <template v-else>
              <td class="admin--table-title">{{ item.name }}</td>
              <td>{{ item.sort_order }}</td>
              <td>
                <span :class="['admin--badge', getStatusBadgeClass(item.status_YN)]">
                  {{ getStatusLabel(item.status_YN) }}
                </span>
              </td>
              <td class="date">{{ formatDate(item.created_at) }}</td>
              <td></td>
            </template>
          </tr>
        </tbody>
      </table>
    </div>

    <!-- 토스트 알림 -->
    <Teleport to="body">
      <Transition name="admin--toast">
        <div
          v-if="toast.show"
          class="admin--toast"
          :class="{ 'is-error': toast.type === 'error' }"
        >
          <span class="admin--toast-icon"></span>
          <span class="admin--toast-msg">{{ toast.message }}</span>
          <button class="admin--toast-close" @click="dismissToast">×</button>
        </div>
      </Transition>
    </Teleport>

    <!-- 알림 모달 -->
    <AdminAlertModal
      v-if="alertModal.show"
      :title="alertModal.title"
      :message="alertModal.message"
      :type="alertModal.type"
      @confirm="handleAlertConfirm"
      @cancel="handleAlertCancel"
      @close="closeAlertModal"
    />

    <!-- 페이지네이션 -->
    <div v-if="totalPages > 1" class="admin--pagination">
      <button
        v-if="totalPages > 2"
        class="admin--pagination-btn"
        :disabled="currentPage === 1"
        @click="changePage(1)"
        title="처음"
      >◀◀</button>
      <button
        class="admin--pagination-btn"
        :disabled="currentPage === 1"
        @click="changePage(currentPage - 1)"
        title="이전"
      >◀</button>
      <button
        v-for="page in visiblePages"
        :key="page"
        class="admin--pagination-btn"
        :class="{ 'is-active': page === currentPage }"
        @click="changePage(page)"
      >{{ page }}</button>
      <button
        class="admin--pagination-btn"
        :disabled="currentPage === totalPages"
        @click="changePage(currentPage + 1)"
        title="다음"
      >▶</button>
      <button
        v-if="totalPages > 2"
        class="admin--pagination-btn"
        :disabled="currentPage === totalPages"
        @click="changePage(totalPages)"
        title="끝"
      >▶▶</button>
    </div>
  </div>
</template>

<script setup>
  import { ref, computed, onMounted } from "vue";
  import AdminAlertModal from "~/components/admin/AdminAlertModal.vue";

  definePageMeta({
    layout: "admin",
    middleware: ["auth"],
  });

  const { get, post } = useApi();

  const isLoading = ref(false);
  const isSaving = ref(false);
  const items = ref([]);
  const currentPage = ref(1);
  const perPage = ref(10);
  const totalCount = ref(0);
  const totalPages = ref(0);

  // 토스트
  const toast = ref({ show: false, type: "success", message: "" });
  let toastTimer = null;
  const showToast = (message, type = "success", duration = type === "error" ? 4500 : 2500) => {
    if (toastTimer) clearTimeout(toastTimer);
    toast.value = { show: true, type, message };
    toastTimer = setTimeout(() => { toast.value.show = false; }, duration);
  };
  const dismissToast = () => {
    if (toastTimer) clearTimeout(toastTimer);
    toast.value.show = false;
  };

  // 신규 행들
  const newRows = ref([]); // [{ _tempId, name, sort_order, status_YN }]
  let tempIdCounter = 0;

  // 수정 중인 행들: { [id]: { name, sort_order, status_YN } }
  const editing = ref({});

  // 삭제 예정 ID들 (저장 시 일괄 처리)
  const markedForDeleteIds = ref([]);

  // 화면에 보이는 기존 행들 (삭제 예정 제외)
  const displayedItems = computed(() =>
    items.value.filter((it) => !markedForDeleteIds.value.includes(it.id))
  );

  // 변경 카운트
  const changeCount = computed(
    () => newRows.value.length + Object.keys(editing.value).length + markedForDeleteIds.value.length
  );
  const hasChanges = computed(() => changeCount.value > 0);

  // 오늘 라벨
  const todayLabel = computed(() => {
    const d = new Date();
    return d.toLocaleDateString("ko-KR", { year: "numeric", month: "2-digit", day: "2-digit" });
  });

  // 체크박스 선택 (보이는 행 기준)
  const selectedIds = ref([]);
  const isAllSelected = computed(
    () => displayedItems.value.length > 0 && displayedItems.value.every((it) => selectedIds.value.includes(it.id))
  );
  const isPartialSelected = computed(
    () => selectedIds.value.length > 0 && !isAllSelected.value
  );
  const toggleAll = (checked) => {
    if (checked) {
      const pageIds = displayedItems.value.map((it) => it.id);
      selectedIds.value = Array.from(new Set([...selectedIds.value, ...pageIds]));
    } else {
      const pageIds = new Set(displayedItems.value.map((it) => it.id));
      selectedIds.value = selectedIds.value.filter((id) => !pageIds.has(id));
    }
  };

  // 알림 모달
  const alertModal = ref({ show: false, title: "알림", message: "", type: "alert", onConfirm: null });
  const showConfirm = (message, onConfirm, title = "확인") => {
    alertModal.value = { show: true, title, message, type: "confirm", onConfirm };
  };
  const closeAlertModal = () => { alertModal.value.show = false; };
  const handleAlertConfirm = () => {
    if (alertModal.value.onConfirm) alertModal.value.onConfirm();
    closeAlertModal();
  };
  const handleAlertCancel = () => closeAlertModal();

  // 페이지 번호
  const visiblePages = computed(() => {
    const pages = [];
    const maxVisible = 5;
    let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
    let end = Math.min(totalPages.value, start + maxVisible - 1);
    if (end - start < maxVisible - 1) start = Math.max(1, end - maxVisible + 1);
    for (let i = start; i <= end; i++) pages.push(i);
    return pages;
  });

  // 데이터 로드
  const loadItems = async () => {
    isLoading.value = true;
    const { data, error } = await get("/species/list", {
      params: { page: currentPage.value, per_page: perPage.value },
    });
    if (error) {
      console.error("[SpeciesList] 목록 로드 실패:", error);
      items.value = [];
      totalCount.value = 0;
      totalPages.value = 0;
    } else if (data?.success && data?.data) {
      items.value = data.data.items || [];
      totalCount.value = data.data.total || 0;
      totalPages.value = data.data.total_pages || 0;
    }
    isLoading.value = false;
  };

  // 신규 행 추가
  const addNewRow = () => {
    dismissToast();
    newRows.value.push({
      _tempId: ++tempIdCounter,
      name: "",
      sort_order: 1,
      status_YN: "Y",
    });
  };

  const removeNewRow = (tempId) => {
    newRows.value = newRows.value.filter((r) => r._tempId !== tempId);
  };

  // 수정 시작
  const startEdit = (item) => {
    dismissToast();
    editing.value = {
      ...editing.value,
      [item.id]: { name: item.name, sort_order: item.sort_order, status_YN: item.status_YN },
    };
  };
  const cancelEdit = (id) => {
    const next = { ...editing.value };
    delete next[id];
    editing.value = next;
  };

  // 모두 취소
  const cancelAll = () => {
    if (!hasChanges.value) return;
    showConfirm(
      "작성·수정·삭제 표시한 모든 변경사항을 취소하시겠습니까?",
      () => {
        newRows.value = [];
        editing.value = {};
        markedForDeleteIds.value = [];
        dismissToast();
      },
      "변경 취소"
    );
  };

  // 일괄 저장
  const bulkSave = async () => {
    dismissToast();
    if (!hasChanges.value) return;

    // 프론트 측 기본 검증
    const creates = newRows.value.map((n) => ({
      name: (n.name || "").trim(),
      sort_order: Number(n.sort_order) || 0,
      status_YN: n.status_YN,
    }));
    const updates = Object.entries(editing.value).map(([id, v]) => ({
      id: Number(id),
      name: (v.name || "").trim(),
      sort_order: Number(v.sort_order) || 0,
      status_YN: v.status_YN,
    }));

    for (let i = 0; i < creates.length; i++) {
      if (!creates[i].name) return showToast(`신규 ${i + 1}행: 구분명을 입력하세요.`, "error");
      if (creates[i].name.length > 30) return showToast(`신규 ${i + 1}행: 구분명 30자 이내`, "error");
      if (creates[i].sort_order < 0) return showToast(`신규 ${i + 1}행: 정렬순서 0 이상`, "error");
    }
    for (let i = 0; i < updates.length; i++) {
      if (!updates[i].name) return showToast(`수정 ${i + 1}행: 구분명을 입력하세요.`, "error");
      if (updates[i].name.length > 30) return showToast(`수정 ${i + 1}행: 구분명 30자 이내`, "error");
      if (updates[i].sort_order < 0) return showToast(`수정 ${i + 1}행: 정렬순서 0 이상`, "error");
    }

    const deletes = [...markedForDeleteIds.value];

    isSaving.value = true;
    try {
      const { data, error } = await post("/species/bulk-save", { creates, updates, deletes });
      if (error || !data?.success) {
        showToast(error?.message || data?.message || "저장에 실패했습니다.", "error");
        return;
      }
      showToast(data.message || "저장되었습니다.", "success");
      newRows.value = [];
      editing.value = {};
      markedForDeleteIds.value = [];
      selectedIds.value = [];
      await loadItems();
    } catch (e) {
      showToast("서버 오류가 발생했습니다.", "error");
      console.error("Bulk save error:", e);
    } finally {
      isSaving.value = false;
    }
  };

  // 선택 삭제 — 즉시 서버 호출 X. 화면에서 사라지고 일괄 저장 시 함께 처리
  const bulkDelete = () => {
    if (selectedIds.value.length === 0) return;
    const ids = [...selectedIds.value];
    // 수정 중이던 행이면 수정 상태도 해제
    const nextEditing = { ...editing.value };
    ids.forEach((id) => { delete nextEditing[id]; });
    editing.value = nextEditing;
    // 삭제 예정에 추가
    markedForDeleteIds.value = Array.from(new Set([...markedForDeleteIds.value, ...ids]));
    selectedIds.value = [];
    dismissToast();
  };

  // 페이지 변경
  const changePage = (page) => {
    if (page < 1 || page > totalPages.value) return;
    if (hasChanges.value) {
      return showConfirm(
        "저장하지 않은 변경사항이 있습니다. 페이지를 이동하면 모두 사라집니다.",
        () => {
          newRows.value = [];
          editing.value = {};
          markedForDeleteIds.value = [];
          selectedIds.value = [];
          currentPage.value = page;
          loadItems();
          window.scrollTo({ top: 0, behavior: "smooth" });
        },
        "페이지 이동"
      );
    }
    currentPage.value = page;
    loadItems();
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  // 라벨/뱃지
  const getStatusLabel = (status) => (status === "Y" ? "사용중" : "미사용");
  const getStatusBadgeClass = (status) => (status === "Y" ? "admin--badge-active" : "admin--badge-ended");

  const formatDate = (dateString) => {
    if (!dateString) return "-";
    const date = new Date(dateString.replace(" ", "T"));
    if (isNaN(date.getTime())) return dateString;
    return date.toLocaleDateString("ko-KR", { year: "numeric", month: "2-digit", day: "2-digit" });
  };

  onMounted(() => {
    loadItems();
  });
</script>
