<script setup lang="ts">
import { ref, computed, onMounted, watch } from "vue";
import { AttachmentsService } from "@/components/service/management/AttachmentsService";
import { ProjectService } from "@/components/service/project/projectService";
// ✅ 부모에서 넘겨준 id 수신 + 닫기 이벤트
const props = defineProps<{ id: number | string }>();
const emit = defineEmits<{ (e: "close"): void }>();

// -------- state --------
const loading = ref(false);
const detailRaw = ref<any | null>(null);

const experimentInfo = ref({
  datasetTitle: "-",
  projectName: "-",
  version: "-",
  createdDate: "-",
  createdId: "-",
  modifiedDate: "-",
  modifiedId: "-",
  description: "-",
  fileName: "-",
  fileSize: "-",
});

// storagePath가 경로(슬래시 포함)이면 우선 사용, 아니면 storedName 사용
const downloadObjectName = computed(() => {
  const sp = detailRaw.value?.storagePath as string | undefined;
  const sn = detailRaw.value?.storedName as string | undefined;
  const raw = sp && /[\\/]/.test(sp) ? sp : sn || sp || "";
  return (raw || "").replace(/^\/+/, "").replace(/\/{2,}/g, "/");
});

async function handleDownload() {
  const key = downloadObjectName.value;
  if (!key) return;

  try {
    // 1차: 정규화된 키로 시도 (경로형/파일명형 모두 커버)
    const res = await AttachmentsService.downloadFile(key);

    // 서버가 에러(JSON) 보낸 경우 감지
    const ct = String(res.headers["content-type"] || "").toLowerCase();
    if (ct.includes("application/json")) {
      const text = await (res.data as Blob).text();
      try {
        const json = JSON.parse(text);
        throw new Error(json.message || text);
      } catch {
        throw new Error(text);
      }
    }

    // 파일명 추출(헤더 없으면 basename으로)
    const cd = res.headers["content-disposition"] || "";
    const mUtf8 = cd.match(/filename\*\s*=\s*UTF-8''([^;]+)/i);
    const mStd = cd.match(/filename\s*=\s*(?:"([^"]+)"|([^;]+))/i);
    let filename =
      (mUtf8 && decodeURIComponent(mUtf8[1].trim())) ||
      (mStd && (mStd[1] || mStd[2])?.trim()) ||
      key.split(/[\\/]/).pop() ||
      "download.bin";

    const blob = new Blob([res.data]);
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.setAttribute("download", filename);
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
  } catch (err) {
    // 2차 폴백: 혹시나 경로형이 안 맞으면 basename으로 재시도
    const base = key.split(/[\\/]/).pop() || key;
    if (base && base !== key) {
      const res2 = await AttachmentsService.downloadFile(base);
      const blob = new Blob([res2.data]);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.setAttribute("download", base);
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
      return;
    }
    throw err;
  }
}

const canDownload = computed(() => !!downloadObjectName.value);

// -------- utils --------
const formatIso = (s?: string) =>
  s ? String(s).replace("T", " ").slice(0, 19) : "-";

const formatBytes = (b?: number) => {
  const n = Number(b);
  if (!Number.isFinite(n) || n < 0) return "-";
  if (n < 1024) return `${n} B`;
  const u = ["KB", "MB", "GB", "TB"];
  let i = -1,
    v = n;
  do {
    v /= 1024;
    i++;
  } while (v >= 1024 && i < u.length - 1);
  return `${v.toFixed(1)} ${u[i]}`;
};

// 백엔드 응답 → 화면 모델
const mapToViewModel = (raw: any) => {
  const projectName =
    raw?.projectName ?? raw?.project?.name ?? raw?.prjNm ?? "-";

  const size = raw?.fileSize ?? raw?.size ?? raw?.length ?? undefined;

  return {
    datasetTitle: raw?.title ?? "-",
    projectName,
    version: raw?.version ?? "-",
    createdDate: formatIso(raw?.regDt),
    createdId: raw?.regUserId ?? "-",
    modifiedDate: formatIso(raw?.modDt),
    modifiedId: raw?.modUserId ?? "-",
    description: raw?.description ?? "-",
    fileName: raw?.originalName ?? "-",
    fileSize: formatBytes(size),
  };
};

async function fetchProjectName(projectId?: number) {
  if (!projectId && projectId !== 0) return;
  try {
    const res = await ProjectService.fetchProjectById(projectId as number);
    const prj = res?.data ?? res;
    experimentInfo.value.projectName = prj?.prjNm ?? prj?.name ?? "-";
  } catch (e) {
    console.warn("[Experiment/View] project fetch fail:", e);
  }
}

const info = computed(() => mapToViewModel(detailRaw.value || {}));

async function fetchDetail(id: number | string) {
  const idNum = typeof id === "string" ? Number(id) : id;
  if (!Number.isFinite(idNum as number)) {
    console.warn("[Datasets/View] invalid id:", id);
    return;
  }

  loading.value = true;
  try {
    const res = await AttachmentsService.view(idNum as number);
    detailRaw.value = res?.data ?? res;

    experimentInfo.value = mapToViewModel(detailRaw.value);
    await fetchProjectName(detailRaw.value?.projectId);
  } catch (e) {
    console.error("[Datasets/View] fetch detail error:", e);
  } finally {
    loading.value = false;
  }
}

// -------- lifecycle --------
onMounted(() => {
  fetchDetail(props.id);
});

watch(
  () => props.id,
  (nv) => {
    if (nv !== undefined && nv !== null && nv !== "") fetchDetail(nv);
  },
);
</script>

<template>
  <v-container fluid class="h-100 pa-5 d-flex flex-column align-center">
    <v-card
      flat
      class="bg-shades-transparent d-flex flex-column justify-center w-100"
    >
      <v-card flat class="bg-shades-transparent w-100">
        <v-card-item class="text-h5 font-weight-bold pt-0 pa-5 pl-0">
          <div class="d-flex flex-row justify-start align-center">
            <div>View Details</div>
          </div>
        </v-card-item>
      </v-card>

      <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-8">
        <v-card-text class="px-6 pb-6 pt-4">
          <v-row align="center" class="py-2">
            <v-col cols="3" class="text-h6 font-weight-bold"
              >Dataset Title
            </v-col>
            <v-col cols="3" class="pa-2">{{
              experimentInfo.datasetTitle
            }}</v-col>
            <v-col cols="3" class="text-h6 font-weight-bold">Version </v-col>
            <v-col cols="3" class="pa-2">{{ experimentInfo.version }}</v-col>
          </v-row>
          <VDivider class="my-2" />
          <!-- Experiment Name -->
          <v-row align="center" class="py-2">
            <v-col cols="3" class="text-h6 font-weight-bold"
              >Project Name
            </v-col>
            <v-col cols="9" class="pa-2">{{
              experimentInfo.projectName
            }}</v-col>
          </v-row>
          <VDivider class="my-2" />
          <v-row align="center" class="py-2">
            <v-col cols="3" class="text-h6 font-weight-bold"
              >Created Date
            </v-col>
            <v-col cols="3" class="pa-2">{{
              experimentInfo.createdDate
            }}</v-col>
            <v-col cols="3" class="text-h6 font-weight-bold">Created ID </v-col>
            <v-col cols="3" class="pa-2">{{ experimentInfo.createdId }}</v-col>
          </v-row>

          <VDivider class="my-2" />

          <!-- Description -->
          <v-row align="center" class="py-2">
            <v-col cols="3" class="text-h6 font-weight-bold">Description</v-col>
            <v-col cols="9" class="pa-2">{{
              experimentInfo.description
            }}</v-col>
          </v-row>
          <VDivider class="my-2" />
          <v-row align="center" class="py-2">
            <v-col cols="3" class="text-h6 font-weight-bold">File</v-col>
            <v-col cols="9" class="pa-2 d-flex align-center">
              <span class="text-truncate">{{ experimentInfo.fileName }}</span>
              <v-btn
                icon
                variant="text"
                size="small"
                class="ml-2"
                :disabled="!canDownload"
                @click="handleDownload"
                aria-label="download"
              >
                <v-icon>mdi-download</v-icon>
              </v-btn>
            </v-col>
          </v-row>
        </v-card-text>
        <div class="d-flex justify-end mb-2">
          <v-btn color="primary" @click="emit('close')"> Back to List </v-btn>
        </div>
      </v-card>
    </v-card>
  </v-container>
</template>

<style scoped>
.v-card-text {
  width: 100% !important;
  border-collapse: collapse;
  /* 전체 테이블 1px 테두리 */
}

.v-card-text th {
  font-size: 20px;
  min-width: 400px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background-color: rgba(255, 255, 255, 0.05);
  font-weight: 600;
  text-align: center;
  white-space: nowrap;
}
.v-card-text td {
  font-size: 16px;
  min-width: 600px;
  padding: 12px 16px;
  text-align: left;
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.v-card-text tr:nth-child(odd) {
  background-color: rgba(255, 255, 255, 0.02);
}
</style>
