<script setup lang="ts">
import {
  ref,
  computed,
  watch,
  nextTick,
  onMounted,
  onBeforeUnmount,
} from "vue";
import Plotly from "plotly.js-dist-min";
import { MlflowService } from "@/components/service/mlflow/MlflowService";

/** 부모에서 받는 값: 제목 라벨은 그대로 쓰고, 데이터는 runId 하나로 조회 */
const props = defineProps<{
  expName: string; // 상단 라벨 유지용 (표시만)
  runId?: string; // ★ 이 값으로만 MLflow 단건 조회
}>();
const emit = defineEmits<{ (e: "close"): void }>();

/* ---------- 상태 ---------- */
const runs = ref<any[]>([]); // 드롭다운/카운트용: 단건이면 길이=1
const loadingRuns = ref(false);
const selectedRunId = ref<string>(props.runId ?? "");
const loadingRunDetail = ref(false);
const runDetail = ref<any | null>(null);

/* 표시용: runs가 비어도 runDetail이 있으면 1로 보이도록 */
const runsLoadedCount = computed(() =>
  runs.value.length > 0 ? runs.value.length : runDetail.value ? 1 : 0,
);

/* ---------- 렌더링용 ---------- */
const runItems = computed(() => {
  // runs(단건) 우선, 없으면 runDetail로 fallback, 그것도 없으면 selectedRunId로 임시 항목
  const source = runs.value?.length
    ? runs.value
    : runDetail.value
      ? [runDetail.value]
      : [];

  const items = source.map((r: any) => {
    const id = r?.info?.run_id || r?.info?.run_uuid || "";
    const name = r?.info?.run_name || id || "(no name)";
    return { value: id, label: name };
  });

  if (items.length === 0 && selectedRunId.value) {
    items.push({ value: selectedRunId.value, label: selectedRunId.value });
  }
  return items;
});

const selectedMetrics = computed(() => {
  const mm: Array<{ key: string; value: number }> =
    runDetail.value?.data?.metrics ?? [];
  return mm.map((m) => ({ key: m.key, value: m.value }));
});

/* ---------- Plotly ---------- */
const elMetrics = ref<HTMLDivElement | null>(null);

function drawCharts() {
  const mm = selectedMetrics.value.filter(
    (m) => typeof m.value === "number" && isFinite(m.value),
  );
  const x = mm.map((m) => m.key);
  const y = mm.map((m) => m.value);

  if (!elMetrics.value) return;

  if (x.length === 0) {
    Plotly.purge(elMetrics.value);
    elMetrics.value.innerHTML =
      '<div style="padding:16px;color:#999;text-align:center;">No Data</div>';
    return;
  }

  const trace: Partial<Plotly.PlotData> = {
    type: "bar",
    x,
    y,
    text: y.map((v) => (typeof v === "number" ? v.toFixed(4) : "")),
    textposition: "auto",
    hovertemplate: "%{x}: %{y}<extra></extra>",
  };
  const layout: Partial<Plotly.Layout> = {
    title: { text: "Metrics" },
    margin: { t: 40, r: 20, b: 60, l: 50 },
    height: 400,
    showlegend: false,
    paper_bgcolor: "rgba(0,0,0,0)",
    plot_bgcolor: "rgba(0,0,0,0)",
    font: { color: "#E0E0E0" },
    xaxis: {
      automargin: true,
      gridcolor: "rgba(255,255,255,0.08)",
      zerolinecolor: "rgba(255,255,255,0.18)",
      linecolor: "rgba(255,255,255,0.18)",
    },
    yaxis: {
      rangemode: "tozero",
      gridcolor: "rgba(255,255,255,0.08)",
      zerolinecolor: "rgba(255,255,255,0.18)",
      linecolor: "rgba(255,255,255,0.18)",
    },
  };
  Plotly.react(elMetrics.value, [trace], layout, {
    displayModeBar: false,
    responsive: true,
  });
}
function resizeCharts() {
  if (elMetrics.value) Plotly.Plots.resize(elMetrics.value);
}

/* ---------- MLflow helpers ---------- */
function normalizeRun(res: any) {
  const v = res?.data?.run ?? res?.run ?? res?.data ?? res;
  return v?.info && v?.data ? v : null;
}

/* ---------- API (runId: KFP run id 또는 MLflow run id) ---------- */
async function fetchRunDetailById(runId: string) {
  loadingRuns.value = true;
  loadingRunDetail.value = true;
  try {
    if (!runId) {
      runDetail.value = null;
      runs.value = [];
      await nextTick();
      drawCharts();
      return;
    }

    let one: any = null;
    // 1) runId가 KFP run id일 수 있음 → kubeflow_run_id 태그로 MLflow run 조회
    try {
      const byTag = await MlflowService.getRunsByKubeflowRunId(runId);
      const raw = byTag?.data ?? byTag;
      const list = raw?.runs ?? raw?.data?.runs ?? (Array.isArray(raw) ? raw : []);
      const first = Array.isArray(list) && list.length > 0 ? list[0] : null;
      if (first?.info?.run_id || first?.info?.run_uuid) {
        one = first?.info && first?.data ? first : null;
      }
    } catch {
      // ignore
    }
    // 2) 못 찾았으면 runId를 MLflow run id로 간주하고 단건 조회
    if (!one) {
      const res = await MlflowService.getExperimentRun(runId);
      one = normalizeRun(res);
    }

    runDetail.value = one;
    runs.value = one ? [one] : [];
    if (!selectedRunId.value) selectedRunId.value = one?.info?.run_id || one?.info?.run_uuid || runId;
    await nextTick();
    drawCharts();
  } catch (e) {
    runDetail.value = null;
    runs.value = [];
    await nextTick();
    drawCharts();
  } finally {
    loadingRunDetail.value = false;
    loadingRuns.value = false;
  }
}

/* ---------- watch & lifecycle ---------- */
// 부모가 준 runId가 바뀌면 재조회
watch(
  () => props.runId,
  (nv) => {
    selectedRunId.value = nv || "";
    fetchRunDetailById(selectedRunId.value);
  },
  { immediate: true },
);

// 드롭다운 변경 시에도 동일하게 단건 조회(템플릿 유지 목적)
watch(selectedRunId, (id, prev) => {
  if (id && id !== prev) fetchRunDetailById(id);
});

// 최초 마운트 시(부모 runId가 이미 세팅된 케이스 포함) 한 번 더 안전하게
onMounted(() => {
  if (selectedRunId.value) fetchRunDetailById(selectedRunId.value);
  window.addEventListener("resize", resizeCharts);
});
onBeforeUnmount(() => window.removeEventListener("resize", resizeCharts));
</script>

<template>
  <v-container fluid class="h-100 pa-5 d-flex flex-column align-center">
    <v-card flat class="w-100 rounded-lg pa-8">
      <v-card-title class="grey lighten-4 py-2 px-4 d-flex align-center justify-space-between">
        <span class="font-weight-bold">Metrics</span>
        <v-btn color="primary" variant="elevated" @click="emit('close')">
          Back to List
        </v-btn>
      </v-card-title>

      <v-card-text class="px-6 pb-2 pt-4">
        <v-row class="mb-4" align="center">
          <v-col
            cols="12"
            class="d-flex align-center justify-between flex-wrap ga-3"
          >
            <div class="text-body-2">
              Runs loaded:
              <strong>{{ runsLoadedCount.toLocaleString() }}</strong>
            </div>

            <v-select
              v-model="selectedRunId"
              :items="runItems"
              item-title="label"
              item-value="value"
              density="comfortable"
              hide-details
              :clearable="false"
              :disabled="runItems.length <= 1"
              style="min-width: 280px; max-width: 440px"
            />
            <v-progress-circular
              v-if="loadingRuns || loadingRunDetail"
              indeterminate
              size="16"
              class="ml-2"
            />
          </v-col>
        </v-row>

        <!-- 선택 run 요약 -->
        <v-card class="mb-6" variant="tonal">
          <v-card-title class="py-2 px-4">Selected Run</v-card-title>
          <v-card-text class="px-4 pb-4">
            <v-row>
              <v-col cols="12" md="6">
                <v-table density="comfortable">
                  <tbody>
                    <tr>
                      <td style="width: 40%">Run ID</td>
                      <td>{{ runDetail?.info?.run_id || "—" }}</td>
                    </tr>
                    <tr>
                      <td>Run Name</td>
                      <td>{{ runDetail?.info?.run_name || "—" }}</td>
                    </tr>
                    <tr>
                      <td>Status</td>
                      <td>{{ runDetail?.info?.status || "—" }}</td>
                    </tr>
                    <tr>
                      <td>Start</td>
                      <td>
                        {{
                          runDetail?.info?.start_time
                            ? new Date(
                                runDetail.info.start_time,
                              ).toLocaleString()
                            : "—"
                        }}
                      </td>
                    </tr>
                    <tr>
                      <td>End</td>
                      <td>
                        {{
                          runDetail?.info?.end_time
                            ? new Date(runDetail.info.end_time).toLocaleString()
                            : "—"
                        }}
                      </td>
                    </tr>
                  </tbody>
                </v-table>
              </v-col>

              <v-col cols="12" md="6">
                <div class="text-subtitle-2 mb-2">Parameters</div>
                <v-table density="compact">
                  <thead>
                    <tr>
                      <th>Key</th>
                      <th>Value</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-if="!runDetail?.data?.params?.length">
                      <td colspan="2" class="text-medium-emphasis">
                        No params
                      </td>
                    </tr>
                    <tr v-for="p in runDetail?.data?.params || []" :key="p.key">
                      <td>{{ p.key }}</td>
                      <td>{{ p.value }}</td>
                    </tr>
                  </tbody>
                </v-table>
              </v-col>
            </v-row>

            <v-row class="mt-4">
              <v-col cols="12" md="6">
                <div class="text-subtitle-2 mb-2">Metrics</div>
                <v-table density="compact">
                  <thead>
                    <tr>
                      <th>Metric</th>
                      <th>Value</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-if="!runDetail?.data?.metrics?.length">
                      <td colspan="2" class="text-medium-emphasis">
                        No metrics
                      </td>
                    </tr>
                    <tr
                      v-for="m in runDetail?.data?.metrics || []"
                      :key="m.key"
                    >
                      <td>{{ m.key }}</td>
                      <td>{{ m.value }}</td>
                    </tr>
                  </tbody>
                </v-table>
              </v-col>

              <v-col cols="12" md="6">
                <div class="text-subtitle-2 mb-2">Tags</div>
                <v-table density="compact">
                  <thead>
                    <tr>
                      <th>Key</th>
                      <th>Value</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-if="!runDetail?.data?.tags?.length">
                      <td colspan="2" class="text-medium-emphasis">No tags</td>
                    </tr>
                    <tr v-for="t in runDetail?.data?.tags || []" :key="t.key">
                      <td>{{ t.key }}</td>
                      <td class="text-truncate" style="max-width: 420px">
                        {{ t.value }}
                      </td>
                    </tr>
                  </tbody>
                </v-table>
              </v-col>
            </v-row>
          </v-card-text>
        </v-card>

        <!-- 요약 테이블 -->
        <v-card flat class="mb-6">
          <v-card-title class="py-2 px-0 text-button text-medium-emphasis">
            Model Metrics (selected run)
          </v-card-title>
          <v-table density="comfortable">
            <thead>
              <tr>
                <th class="text-left" style="width: 50%">Metric</th>
                <th class="text-left">Value</th>
              </tr>
            </thead>
            <tbody>
              <tr v-if="!selectedMetrics.length">
                <td colspan="2" class="text-center py-6 text-medium-emphasis">
                  No Data
                </td>
              </tr>
              <tr v-for="m in selectedMetrics" :key="m.key">
                <td>{{ m.key }}</td>
                <td>{{ m.value }}</td>
              </tr>
            </tbody>
          </v-table>
        </v-card>

        <!-- 차트 -->
        <v-card flat class="mb-6">
          <v-card-title class="py-2 px-0 text-button text-medium-emphasis">
            Metrics (bar chart)
          </v-card-title>
          <div ref="elMetrics" style="width: 100%; height: 400px"></div>
        </v-card>
      </v-card-text>
    </v-card>
  </v-container>
</template>
