<script setup lang="ts">
import { onMounted, ref, computed, watch } from "vue";
import Plotly from "plotly.js-dist-min";
import { WorkflowService } from "@/components/service/management/WorkflowService";
import { ExecutionsService } from "@/components/service/management/ExecutionsService";
import { AttachmentsService } from "@/components/service/management/AttachmentsService";
import { useAutoflowStore } from "@/stores/autoflowStore";

const store = useAutoflowStore();
const currentProjectId = computed(() => store.projectId);

const pieChartRef = ref<HTMLElement | null>(null);
const workflows = ref<any[]>([]);
const recentLimit = 10;
const runsLoading = ref(false);
const recentRuns = ref<
  {
    name: string;
    status: "success" | "failed" | "running" | "pending";
    time: string;
  }[]
>([]);
// dataset
const dsLoading = ref(false);
type DsItem = {
  name: string;
  version: number;
  rows: number;
  last?: string;
  pct: number;
};
const dsItems = ref<DsItem[]>([]);
const dsWindowDays = ref<7 | 30 | 90>(30);

// 날짜 유틸
const toTime = (x?: string) => new Date(x ?? 0).getTime();
const fmtYmd = (iso?: string) => (iso ? new Date(iso).toLocaleString() : "-");

async function loadDatasetActivity() {
  dsLoading.value = true;
  try {
    const payload = {
      projectId: currentProjectId.value,
      page: 0,
      size: 1000,
      refType: "DATASET",
      sortField: "id",
      sortDirection: "DESC",
    };

    const res = await AttachmentsService.search(payload as any);
    const list: any[] = res?.data?.content ?? res?.data ?? [];

    const map = new Map<
      string,
      { name: string; version: number; rows: number; last?: string }
    >();

    for (const a of list) {
      const name = String(a?.title ?? a?.originalName ?? "(no name)");
      const v = Number(a?.version) || 1; // null 방어
      const reg = (a?.modDt ?? a?.regDt ?? a?.createdAt) as string | undefined;

      const cur = map.get(name) ?? {
        name,
        version: 0,
        rows: 0,
        last: undefined,
      };
      cur.rows += 1;
      cur.version = Math.max(cur.version, v); // 최신 버전 반영
      if (!cur.last || (reg && toTime(reg) > toTime(cur.last))) cur.last = reg;
      map.set(name, cur);
    }

    const arr = Array.from(map.values());
    const maxVer = Math.max(1, ...arr.map((i) => i.version));

    dsItems.value = arr
      .map((i) => ({ ...i, pct: Math.round((i.version / maxVer) * 100) }))
      .sort((a, b) => toTime(b.last) - toTime(a.last) || b.version - a.version);
  } catch (e) {
    console.error("[Home] loadDatasetActivity error:", e);
    dsItems.value = [];
  } finally {
    dsLoading.value = false;
  }
}

function toUiStatus(state?: string) {
  switch ((state || "").toUpperCase()) {
    case "SUCCEEDED":
      return "success";
    case "FAILED":
      return "failed";
    case "RUNNING":
      return "running";
    case "PENDING":
      return "pending";
    default:
      return "pending";
  }
}

function fmtYmdHm(iso?: string) {
  if (!iso) return "-";
  const d = new Date(iso);
  const p = (n: number) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
}

async function loadRecentRuns() {
  runsLoading.value = true;
  try {
    const all: any[] = [];
    const seen = new Set<string>();

    // 첫 페이지
    let page = await ExecutionsService.search({ pageSize: 200 });
    all.push(...(page?.data?.runs ?? []));
    let token = page?.data?.next_page_token ?? page?.data?.nextPageToken;

    // 다음 페이지들(필요 시)
    let guard = 0;
    while (token && !seen.has(token) && guard < 20) {
      seen.add(token);

      // snake_case 우선
      page = await ExecutionsService.search({
        pageToken: token,
        pageSize: 200,
      } as any);
      all.push(...(page?.data?.runs ?? []));
      token = page?.data?.next_page_token ?? page?.data?.nextPageToken;
      guard++;
    }

    // 중복 제거
    const dedup = Array.from(
      new Map(all.map((r) => [r?.run_id ?? r?.id ?? r?.name, r])).values(),
    );

    // (선택) 프로젝트 필터가 필요하면 여기에서 필터
    // const filtered = dedup.filter(r => String(r?.projectId ?? "") === String(currentProjectId.value));

    const latest = dedup
      .sort(
        (a, b) =>
          new Date(b?.created_at ?? 0).getTime() -
          new Date(a?.created_at ?? 0).getTime(),
      )
      .slice(0, recentLimit)
      .map((r) => ({
        name: r?.display_name ?? r?.name ?? r?.run_id ?? "(no name)",
        status: toUiStatus(r?.state),
        time: fmtYmdHm(r?.created_at),
      }));

    recentRuns.value = latest;
  } catch (e) {
    console.error("[Home] loadRecentRuns error:", e);
    recentRuns.value = [];
  } finally {
    runsLoading.value = false;
  }
}

function renderStatusPie() {
  if (!pieChartRef.value) return;

  // 1) 상태별 고정 팔레트
  const COLOR = {
    SUCCEEDED: "#2ecc71",
    FAILED: "#e74c3c",
    RUNNING: "#3498db",
    PENDING: "#f1c40f",
    CREATED: "#3498db",
    SKIPPED: "#95a5a6",
    UNKNOWN: "#7f8c8d",
    NODATA: "#4b4f55",
  };

  // 2) 집계
  const counts = new Map<string, number>();
  for (const wf of workflows.value ?? []) {
    const raw = (wf?.kubeflowStatus ?? wf?.kubeflow_status ?? "UNKNOWN") + "";
    const status = raw.toUpperCase().trim();
    counts.set(status, (counts.get(status) || 0) + 1);
  }

  // 3) No Data 전용 처리 (중립 색 + 중앙 텍스트 / 범례 숨김)
  if (counts.size === 0) {
    const trace: Partial<Plotly.PlotData> = {
      values: [1],
      labels: ["No Data"],
      type: "pie",
      hole: 0.55,
      textinfo: "none",
      marker: { colors: [COLOR.NODATA] },
      hoverinfo: "skip",
    };

    const layout: Partial<Plotly.Layout> = {
      paper_bgcolor: "#1e1e1e",
      plot_bgcolor: "#1e1e1e",
      showlegend: false,
      margin: { t: 20, b: 40, l: 0, r: 0 },
      annotations: [
        {
          text: "<b>No Data</b>",
          showarrow: false,
          font: { color: "#ffffff", size: 16 },
        },
      ],
    };

    Plotly.react(pieChartRef.value, [trace], layout, { displayModeBar: false });
    return;
  }

  // 4) 데이터가 있을 때: 상태별 색 지정
  const labels = Array.from(counts.keys());
  const values = Array.from(counts.values());
  const colors = labels.map((s) => {
    if (s.includes("SUCCEED")) return COLOR.SUCCEEDED;
    if (s.includes("FAIL")) return COLOR.FAILED;
    if (s.includes("RUN")) return COLOR.RUNNING;
    if (s.includes("CREATE")) return COLOR.CREATED;
    if (s.includes("PEND")) return COLOR.PENDING;
    if (s.includes("SKIP")) return COLOR.SKIPPED;
    return COLOR.UNKNOWN;
  });

  const trace: Partial<Plotly.PlotData> = {
    values,
    labels,
    type: "pie",
    hole: 0.4,
    textinfo: "label+percent",
    textfont: { color: "#fff", size: 13 },
    marker: { colors },
    hovertemplate: "%{label}: %{percent}<extra></extra>",
  };

  const layout: Partial<Plotly.Layout> = {
    paper_bgcolor: "#1e1e1e",
    plot_bgcolor: "#1e1e1e",
    showlegend: true,
    legend: {
      font: { color: "#ffffff", size: 12 },
      orientation: "h",
      x: 0.5,
      xanchor: "center",
      y: -0.2,
    },
    margin: { t: 20, b: 40, l: 0, r: 0 },
  };

  Plotly.react(pieChartRef.value, [trace], layout, { displayModeBar: false });
}

const datasetUpdates = [
  { name: "DrivingLog2025", count: 7 },
  { name: "CameraFrames", count: 3 },
  { name: "LidarScans", count: 2 },
  { name: "Traffic_log", count: 2 },
  { name: "Traffic_log2", count: 2 },
];

const tableHeader = [
  { label: "Model Name", width: "10%", style: "word-break: keep-all;" },
  { label: "Version", width: "10%", style: "word-break: keep-all;" },
  { label: "Deployed At", width: "10%", style: "word-break: keep-all;" },
  { label: "Status", width: "10%", style: "word-break: keep-all;" },
  { label: "Download", width: "10%", style: "word-break: keep-all;" },
];

const data = ref({
  results: [
    {
      deviceKey: "1",
      name: "LaneDetectionModel",
      version: "v1.2.0",
      time: "2025-05-13 14:32",
      status: "Active",
      download: "Finished",
    },
    {
      deviceKey: "2",
      name: "TrafficSignClassifier",
      version: "v0.9.3",
      time: "2025-05-13 09:00",
      status: "Pending",
      download: "-",
    },
    {
      deviceKey: "3",
      name: "PathPlannerModel",
      version: "v2.0.1",
      time: "2025-05-12 17:44",
      status: "Failed",
      download: "Failed",
    },
  ],
  allSelected: false,
  selected: [],
});

const handleRefresh = () => {
  alert("Refresh 작업 진행중...");
};
const getSelectedAllData = () => {
  data.value.selected = data.value.allSelected
    ? data.value.results.map(({ deviceKey }) => ({ deviceKey }))
    : [];
};

const getLatestTimestamp = (wf: any): string => wf.modDt;

// "YYYY-MM-DD HH:mm" 포맷
const formatToYmdHm = (isoString: string): string => {
  if (!isoString) return "-";
  const d = new Date(isoString);
  const pad = (n: number) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
};

const recentWorkflowList = computed(() => {
  return (workflows.value ?? [])
    .map((wf: any) => ({
      id: wf.id,
      title: wf.name,
      timestamp: getLatestTimestamp(wf),
    }))
    .filter((item) => item.title && item.timestamp)
    .sort(
      (a, b) =>
        new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),
    )
    .slice(0, recentLimit);
});

// ---- 데이터 로드 & 차트 갱신 ----
async function loadWorkflows() {
  try {
    const payload = {
      page: 0,
      size: 1000,
      projectId: currentProjectId.value,
      sortField: "id",
      sortDirection: "DESC",
    };

    const res = await WorkflowService.search(payload);
    const raw = Array.isArray(res?.data?.content)
      ? res.data.content
      : Array.isArray(res?.data)
        ? res.data
        : [];

    workflows.value = raw.filter(
      (wf: any) =>
        String(
          wf?.projectId ?? wf?.prjId ?? wf?.project_id ?? wf?.project?.id ?? "",
        ) === String(currentProjectId.value),
    );

    renderStatusPie();
  } catch (err) {
    console.error("GET /api/workflows failed:", err);
    workflows.value = [];
    renderStatusPie();
  }
}

onMounted(async () => {
  renderStatusPie();
  await loadRecentRuns();
  await loadWorkflows();
  await loadDatasetActivity();
});

// 프로젝트 변경 시 재조회
watch(currentProjectId, () => loadWorkflows());
</script>

<template>
  <v-container fluid>
    <div class="d-flex justify-space-between align-center mb-6">
      <h2 class="text-h6 font-weight-bold">배터리 상태 예측 모델 프로젝트</h2>
      <v-btn color="primary" prepend-icon="mdi-refresh" @click="handleRefresh"
        >Refresh</v-btn
      >
    </div>

    <v-row>
      <v-col cols="12" md="6">
        <v-card class="pa-0" style="min-height: 360px; max-height: 360px">
          <div style="padding: 16px; border-bottom: 1px solid #ccc">
            <h3 class="text-subtitle-1 font-weight-bold mb-0">
              Workflow Success Rate
            </h3>
          </div>
          <div style="overflow-y: auto; padding: 8px 16px">
            <div ref="pieChartRef" style="height: 280px"></div>
          </div>
        </v-card>
      </v-col>
      <v-col cols="12" md="6">
        <v-card class="pa-0" style="min-height: 360px; max-height: 360px">
          <div style="padding: 16px; border-bottom: 1px solid #ccc">
            <h3 class="text-subtitle-1 font-weight-bold mb-0">
              Recently Registered Workflow
            </h3>
          </div>
          <div style="overflow-y: auto; max-height: 300px; padding: 8px 16px">
            <v-list density="comfortable" nav>
              <v-list-item v-for="item in recentWorkflowList" :key="item.id">
                <template #title>
                  <div class="d-flex justify-space-between align-center w-100">
                    <span class="text-body-2 font-weight-medium">{{
                      item.title
                    }}</span>
                    <span class="text-caption text-grey-lighten-1">
                      {{ formatToYmdHm(item.timestamp) }}
                    </span>
                  </div>
                </template>
              </v-list-item>

              <v-list-item v-if="recentWorkflowList.length === 0">
                <template #title>
                  <div class="text-caption text-grey">
                    최근 등록/수정된 워크플로우가 없습니다.
                  </div>
                </template>
              </v-list-item>
            </v-list>
          </div>
        </v-card>
      </v-col>
    </v-row>

    <v-row class="mt-4">
      <v-col cols="12" md="6">
        <v-card class="pa-0" style="min-height: 360px; max-height: 360px">
          <div style="padding: 16px; border-bottom: 1px solid #ccc">
            <h3 class="text-subtitle-1 font-weight-bold mb-0">Recent Run</h3>
          </div>

          <div style="overflow-y: auto; max-height: 300px; padding: 8px 16px">
            <!-- 로딩 표시 -->
            <v-skeleton-loader
              v-if="runsLoading"
              type="list-item-two-line"
              class="mb-2"
              v-for="i in 4"
              :key="i"
            />

            <!-- 데이터 있을 때 -->
            <v-list v-else density="comfortable">
              <v-list-item
                v-for="(run, idx) in recentRuns"
                :key="idx"
                class="py-2"
              >
                <!-- 기존 div 대신 이 블록으로 교체 -->
                <div class="d-flex align-center justify-space-between w-100">
                  <!-- 왼쪽: 상태칩 + (선택) 아이콘 -->
                  <div class="d-flex align-center ga-2">
                    <!-- 아이콘을 계속 쓰고 싶으면 유지, 아니면 이 v-avatar는 삭제해도 됨 -->
                    <v-avatar
                      size="28"
                      :color="
                        run.status === 'success'
                          ? 'green-lighten-1'
                          : run.status === 'failed'
                            ? 'red-lighten-1'
                            : run.status === 'running'
                              ? 'blue-lighten-1'
                              : 'grey-darken-1'
                      "
                    >
                      <v-icon size="20" color="white">
                        {{
                          run.status === "success"
                            ? "mdi-check"
                            : run.status === "failed"
                              ? "mdi-close"
                              : run.status === "running"
                                ? "mdi-progress-clock"
                                : "mdi-clock-outline"
                        }}
                      </v-icon>
                    </v-avatar>
                    <v-chip
                      size="small"
                      :color="
                        run.status === 'success'
                          ? 'success'
                          : run.status === 'failed'
                            ? 'error'
                            : run.status === 'running'
                              ? 'info'
                              : 'grey'
                      "
                      variant="tonal"
                      class="text-uppercase"
                    >
                      {{ run.status }}
                    </v-chip>
                  </div>

                  <!-- 오른쪽: 이름/시간(오른쪽 정렬) -->
                  <div
                    class="d-flex flex-column text-right"
                    style="min-width: 220px"
                  >
                    <span class="font-weight-medium text-body-2 truncate">
                      {{ run.name }}
                    </span>
                    <span class="text-caption text-grey-darken-1">
                      {{ run.time }}
                    </span>
                  </div>
                </div>
              </v-list-item>
              <!-- 빈 상태 -->
              <v-list-item v-if="!runsLoading && recentRuns.length === 0">
                <template #title>
                  <div class="text-caption text-grey">
                    최근 실행 데이터가 없습니다.
                  </div>
                </template>
              </v-list-item>
            </v-list>
          </div>
        </v-card>
      </v-col>
      <v-col cols="12" md="6">
        <v-card class="pa-0" style="min-height: 360px; max-height: 360px">
          <div style="padding: 16px; border-bottom: 1px solid #ccc">
            <div class="d-flex align-center justify-space-between w-100">
              <h3 class="text-subtitle-1 font-weight-bold mb-0">
                Dataset Update Activity
              </h3>
            </div>
          </div>

          <div style="overflow-y: auto; max-height: 300px; padding: 8px 16px">
            <v-skeleton-loader
              v-if="dsLoading"
              type="list-item-three-line"
              class="mb-2"
              v-for="i in 5"
              :key="i"
            />

            <v-list v-else density="comfortable">
              <v-list-item v-for="it in dsItems" :key="it.name" class="py-2">
                <div class="d-flex justify-space-between align-center w-100">
                  <span class="text-body-2 font-weight-medium"
                    >{{ it.name }}
                    <v-chip
                      size="small"
                      color="primary"
                      variant="tonal"
                      class="py-2"
                    >
                      v{{ it.version }}
                    </v-chip></span
                  >

                  <!-- 최신 버전 칩 -->
                  <div class="d-flex align-center ga-2">
                    <span class="text-caption text-medium-emphasis">
                      Last: {{ fmtYmd(it.last) }}
                    </span>
                  </div>
                </div>

                <v-progress-linear
                  :model-value="it.pct"
                  height="8"
                  color="primary"
                  class="mt-1"
                />
                <div class="text-caption text-grey mt-1">
                  {{ it.version }} Update{{ it.version > 1 ? "s" : "" }}
                  <span v-if="it.rows && it.rows !== it.version">
                    • {{ it.rows }} Rows</span
                  >
                </div>
              </v-list-item>

              <v-list-item v-if="!dsLoading && dsItems.length === 0">
                <template #title>
                  <div class="text-caption text-grey">
                    표시할 데이터셋이 없습니다.
                  </div>
                </template>
              </v-list-item>
            </v-list>
          </div>
        </v-card>
      </v-col>
    </v-row>

    <v-card class="rounded-lg pa-4 mt-4">
      <div class="d-flex justify-space-between align-center mt-8 mb-2 px-2">
        <div class="d-flex align-center">
          <span class="text-subtitle-1 font-weight-bold">Model Deployment</span>
        </div>
        <v-btn
          variant="text"
          class="text-caption font-weight-bold"
          append-icon="mdi-arrow-right"
          style="text-transform: none"
        >
          Go to Model Deploy
        </v-btn>
      </div>
      <v-col cols="12">
        <v-sheet>
          <v-table density="comfortable" fixed-header height="625">
            <colgroup>
              <col style="width: 5%" />
              <col
                v-for="(item, i) in tableHeader"
                :key="i"
                :style="`width:${item.width}`"
              />
            </colgroup>
            <thead>
              <tr>
                <th>
                  <v-checkbox
                    v-model="data.allSelected"
                    style="min-width: 36px"
                    :indeterminate="data.allSelected === true"
                    hide-details
                    @change="getSelectedAllData"
                  ></v-checkbox>
                </th>
                <th
                  v-for="(item, i) in tableHeader"
                  :key="i"
                  class="text-center font-weight-bold"
                  :style="item.style"
                >
                  {{ item.label }}
                </th>
              </tr>
            </thead>
            <tbody class="text-body-2">
              <tr
                v-for="(item, i) in data.results"
                :key="i"
                class="text-center"
              >
                <td>
                  <v-checkbox
                    v-model="data.selected"
                    hide-details
                    :value="{ deviceKey: item.deviceKey }"
                  />
                </td>
                <td>{{ item.name }}</td>
                <td>{{ item.version }}</td>
                <td>{{ item.time }}</td>
                <td>{{ item.status }}</td>
                <td>{{ item.download }}</td>
              </tr>
            </tbody>
          </v-table>
        </v-sheet>
      </v-col>
    </v-card>
  </v-container>
</template>

<style scoped>
ul {
  list-style: none;
  padding-left: 0;
  margin-top: 8px;
}
li {
  margin-bottom: 8px;
}
</style>
