<script setup lang="ts">
import { ref, computed, onMounted, watch } from "vue";
import { KubeflowRunService } from "@/components/service/management/KubeflowRunService";
import { KubeflowService } from "@/components/service/management/kubeflowService";
import DetailComponent from "@/components/templates/run/experiment/DetailComponent.vue";

const getProjectId = (): number => {
  const v = Number(localStorage.getItem("projectId"));
  return Number.isFinite(v) ? v : 0;
};

const props = defineProps<{ experimentInfo: any }>();
const emit = defineEmits<{ (e: "close"): void }>();

const showDetail = ref(false);
const detailProps = ref<{ expName: string; runId: string } | null>(null);

// 상단 정보 그대로 바인딩
const header = computed(() => ({
  experimentName: props.experimentInfo?.name ?? "",
  projectName:
    localStorage.getItem("projectName") ||
    props.experimentInfo?.projectName ||
    "",
  createdDate: props.experimentInfo?.createdDate ?? "",
  createdId: props.experimentInfo?.createdID ?? "",
  description: props.experimentInfo?.description ?? "",
  kubeFlowId: props.experimentInfo?.deviceKey ?? "",
  mlFlowId: props.experimentInfo?.mlFlowId ?? "",
}));

// 로딩/데이터 상태
const loading = ref(false);
const experimentId = ref<string>("");
const runs = ref<any[]>([]);

function toMillis(v: unknown): number | null {
  if (v === null || v === undefined || v === "") return null;

  // 숫자(혹은 숫자 문자열) => 초/밀리초 자동 판별
  const n = typeof v === "number" ? v : Number(v as any);
  if (!Number.isNaN(n)) {
    // 1e12 기준: 밀리초(>), 초(<=)
    return n > 1e12 ? Math.trunc(n) : Math.trunc(n * 1000);
  }

  // ISO 문자열
  const t = Date.parse(String(v));
  return Number.isNaN(t) ? null : t;
}

function fmtTsAny(v?: unknown): string {
  const ms = toMillis(v);
  if (ms == null) return "-";
  const d = new Date(ms);
  if (Number.isNaN(d.getTime())) return "-";
  const pad = (x: number) => String(x).padStart(2, "0");
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(
    d.getHours(),
  )}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
}

function fmtDurationAny(start?: unknown, end?: unknown): string {
  const s = toMillis(start);
  const e = toMillis(end);
  if (s == null || e == null || e < s) return "-";
  const diff = e - s;
  const sec = Math.floor(diff / 1000);
  const h = Math.floor(sec / 3600);
  const m = Math.floor((sec % 3600) / 60);
  const s2 = sec % 60;
  const pad = (x: number) => String(x).padStart(2, "0");
  return `${h}:${pad(m)}:${pad(s2)}`;
}
const toUiStatus = (status?: string) => {
  switch ((status || "").toUpperCase()) {
    case "FINISHED":
    case "SUCCEEDED":
      return "Succeeded";
    case "FAILED":
      return "Failed";
    case "RUNNING":
      return "Running";
    case "PENDING":
      return "Pending";
    default:
      return status || "-";
  }
};

const runRows = computed(() =>
  runs.value.map((r: any) => {
    const info = r?.info ?? {};
    const tags: Array<{ key: string; value: string }> = r?.data?.tags ?? [];
    const tag = (k: string) => tags.find((t) => t.key === k)?.value;

    // pipeline 추론 그대로
    const sourceName = tag("mlflow.source.name") || "";
    const pipeline =
      sourceName
        .split("/")
        .pop()
        ?.replace(/\.[^/.]+$/, "") ||
      tag("mlflow.runName") ||
      info?.run_name ||
      "-";

    return {
      runName: info?.run_name || tag("mlflow.runName") || "-",
      status: toUiStatus(info?.status),
      // ▼ 여기 변경
      duration: fmtDurationAny(info?.start_time, info?.end_time),
      pipeline,
      startTime: fmtTsAny(info?.start_time),
      raw: r,
    };
  }),
);

// 페이지네이션
const page = ref(1);
const pageSize = ref(10);
const pageSizeOptions = [
  { text: "10", value: 10 },
  { text: "25", value: 25 },
  { text: "50", value: 50 },
];
const totalPages = computed(() =>
  Math.max(1, Math.ceil(runRows.value.length / pageSize.value)),
);
const pagedRows = computed(() => {
  const start = (page.value - 1) * pageSize.value;
  return runRows.value.slice(start, start + pageSize.value);
});

// 백엔드 Run(실행) 목록 한 건을 runRows가 쓰는 형태로 변환
function backendRunToRunShape(r: any) {
  const createdAt = r?.createdAt ?? r?.startTime ?? r?.startedAt ?? r?.start_time;
  const finishedAt = r?.finishedAt ?? r?.endTime ?? r?.end_time ?? r?.end_time;
  return {
    info: {
      run_name: r?.displayName ?? r?.name ?? r?.runId ?? "-",
      run_id: r?.runId ?? r?.run_id ?? r?.id,
      start_time: createdAt,
      end_time: finishedAt,
      status: r?.state ?? r?.status ?? r?.lifecycle_state,
    },
    data: { tags: r?.data?.tags ?? [] },
    raw: r,
  };
}

// 실행(Run) 목록 API로 전체 run 조회 후, KFP experiment 이름으로 필터 (Execution 목록과 동일한 데이터 소스)
async function fetchRunsByExperimentName(expName: string) {
  if (!expName) return;
  loading.value = true;
  try {
    const projectId = getProjectId();
    if (!projectId) {
      runs.value = [];
      return;
    }

    // Execution 목록과 동일: /api/kubeflow/runs/search (experimentId 없이 전체)
    const res = await KubeflowRunService.search({
      projectId: projectId as any,
      page: 0,
      size: 1000,
      sortField: "createdAt",
      sortDirection: "DESC",
    });
    const result = res?.data ?? res;
    let list: any[] = [];
    if (Array.isArray(result)) list = result;
    else if (Array.isArray(result?.content)) list = result.content;
    else if (Array.isArray(result?.data)) list = result.data;
    else if (Array.isArray(result?.runs)) list = result.runs;

    if (list.length === 0) {
      runs.value = [];
      return;
    }

    // run별 experimentId로 KFP experiment 이름 조회 (Execution 목록과 동일 방식)
    const expIds = [...new Set(list.map((r: any) => r.experimentId ?? r.experiment_id ?? r.experiment?.id).filter(Boolean))];
    const expNameById: Record<string, string> = {};
    await Promise.all(
      expIds.map(async (id: string | number) => {
        try {
          const expRes = await KubeflowService.experimentData(String(id));
          const body = expRes?.data ?? expRes ?? {};
          expNameById[String(id)] = body.display_name ?? body.name ?? body.experiment_name ?? String(id);
        } catch {
          expNameById[String(id)] = String(id);
        }
      }),
    );

    const expNameLower = String(expName).toLowerCase().trim();
    const filtered = list.filter((r: any) => {
      const runExpId = r.experimentId ?? r.experiment_id ?? r.experiment?.id;
      const runExpName = (expNameById[String(runExpId)] ?? r.experiment?.displayName ?? r.experiment?.name ?? "").toLowerCase().trim();
      return runExpName === expNameLower;
    });

    experimentId.value = "";
    runs.value = filtered.map(backendRunToRunShape);
  } catch (e) {
    console.error("[Experiment runs] fetch error:", e);
    runs.value = [];
  } finally {
    loading.value = false;
  }
}

function onRunRowClick(row: any) {
  const runId = row?.raw?.info?.run_id || row?.raw?.info?.run_uuid || "";
  const expName = header.value.experimentName;
  if (!runId || !expName) return;

  // 열기
  detailProps.value = { expName, runId };
  showDetail.value = true;
}

// 초기/변경 시 호출
onMounted(() => {
  fetchRunsByExperimentName(header.value.experimentName);
});
watch(
  () => ({ name: header.value.experimentName, mlFlowId: header.value.mlFlowId }),
  () => fetchRunsByExperimentName(header.value.experimentName),
  { deep: true },
);
</script>

<template>
  <!-- 목록 화면 -->
  <div v-if="!showDetail" class="w-100">
    <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-space-between align-center w-100">
              <div>View Details</div>
              <v-btn color="primary" variant="elevated" @click="emit('close')">
                Back to List
              </v-btn>
            </div>
          </v-card-item>
        </v-card>

        <!-- Experiment Information -->
        <v-card
          flat
          class="bordered-box mb-6 w-100 rounded-lg pa-8 position-relative"
        >
          <v-card-title class="grey lighten-4 py-2 px-4">
            <span class="font-weight-bold">Experiment Information</span>
          </v-card-title>

          <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"
                >Experiment Name</v-col
              >
              <v-col cols="9" class="pa-2">{{ header.experimentName }}</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"
                >Project Name</v-col
              >
              <v-col cols="9" class="pa-2">{{ header.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 ID</v-col
              >
              <v-col cols="3" class="pa-2">{{ header.createdId }}</v-col>
              <v-col cols="3" class="text-h6 font-weight-bold"
                >Created Date</v-col
              >
              <v-col cols="3" class="pa-2">{{ header.createdDate }}</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"
                >Description</v-col
              >
              <v-col cols="9" class="pa-2">{{ header.description }}</v-col>
            </v-row>
          </v-card-text>

          <v-overlay
            :model-value="loading"
            contained
            persistent
            class="align-center justify-center"
          >
            <v-progress-circular indeterminate size="48" />
          </v-overlay>
        </v-card>

        <!-- Runs -->
        <v-card class="rounded-lg pa-8 w-100">
          <v-card-title class="grey lighten-4 py-2 px-4">
            <span class="font-weight-bold">Runs</span>
          </v-card-title>

          <v-card-text class="px-6 pb-2 pt-4">
            <div class="d-flex align-center justify-between mb-4">
              <div class="text-body-2">
                총 {{ runRows.length.toLocaleString() }}개 · Experiment ID:
                <strong>{{ experimentId || "-" }}</strong>
              </div>
            </div>

            <v-table density="comfortable" fixed-header height="420">
              <colgroup>
                <col style="width: 30%" />
                <col style="width: 12%" />
                <col style="width: 14%" />
                <col style="width: 24%" />
                <col style="width: 20%" />
              </colgroup>

              <thead>
                <tr>
                  <th class="text-left">Run Name</th>
                  <th class="text-center">Status</th>
                  <th class="text-center">Duration</th>
                  <th class="text-left">Pipeline</th>
                  <th class="text-center">Start Time</th>
                </tr>
              </thead>

              <tbody class="text-body-2">
                <tr v-if="pagedRows.length === 0">
                  <td colspan="5" class="text-center py-6 text-medium-emphasis">
                    No runs
                  </td>
                </tr>

                <tr
                  v-for="(r, i) in pagedRows"
                  :key="r.raw?.info?.run_id || i"
                  class="run-row"
                  role="button"
                  tabindex="0"
                  @click="onRunRowClick(r)"
                  @keydown.enter.prevent="onRunRowClick(r)"
                  @keydown.space.prevent="onRunRowClick(r)"
                >
                  <td class="text-left text-truncate" :title="r.runName">
                    {{ r.runName }}
                  </td>
                  <td class="text-center">
                    <v-icon v-if="r.status === 'Succeeded'" color="green"
                      >mdi-check-circle</v-icon
                    >
                    <v-icon v-else-if="r.status === 'Failed'" color="red"
                      >mdi-close-circle</v-icon
                    >
                    <v-progress-circular
                      v-else-if="r.status === 'Running'"
                      indeterminate
                      size="18"
                      width="2"
                      color="info"
                    />
                    <v-icon v-else color="grey">mdi-help-circle</v-icon>
                    <span class="ml-1">{{ r.status }}</span>
                  </td>
                  <td class="text-center">{{ r.duration }}</td>
                  <td class="text-left text-truncate" :title="r.pipeline">
                    {{ r.pipeline }}
                  </td>
                  <td class="text-center">{{ r.startTime }}</td>
                </tr>
              </tbody>
            </v-table>

            <v-card-actions class="text-center mt-6 justify-center">
              <v-pagination
                v-model="page"
                :length="totalPages"
                :total-visible="10"
                color="primary"
                rounded="circle"
              />
            </v-card-actions>
          </v-card-text>
        </v-card>
      </v-card>
    </v-container>
  </div>

  <!-- 디테일 화면 -->
  <div v-else class="w-100">
    <DetailComponent
      v-if="detailProps"
      :exp-name="detailProps.expName"
      :run-id="detailProps.runId"
      @close="showDetail = false"
    />
  </div>
</template>

<style scoped>
.run-row {
  cursor: pointer;
  transition: background-color 0.12s ease;
}
.run-row:hover {
  background: rgba(255, 255, 255, 0.06);
}
.run-row:focus {
  outline: 2px solid #3b82f6;
  outline-offset: -2px;
}
</style>
