<template>
  <div>
    <PageDescription>
      <h1>배양 그래프 (멀티)</h1>
      <div class="box">
        <h2>1. 그래프 구성 및 기능</h2>
        <ul>
          <li>총 30개의 그래프를 한 화면에 동시에 볼 수 있습니다.</li>
          <li>렌더링 최적화를 위해 최소한의 기능만 제공됩니다.</li>
        </ul>
      </div>
      <div class="box">
        <h2>2. 출력되는 데이터 개수</h2>
        <ul>
          <li>
            그래프 30개 × 시리즈 12개 × 10분 간격(100시간, 601포인트) =
            <span class="highlight">216,360개</span>
          </li>
          <li>화면 렌더링 시간은 약 600ms ~ 800ms 정도 소요됩니다.</li>
        </ul>
      </div>
      <div class="box">
        <h2>3. 그래프 복사</h2>
        <ul>
          <li>
            <span class="highlight">그래프 복사</span> 버튼을 클릭하면 그래프가
            클립보드에 복사됩니다.
          </li>
        </ul>
      </div>
    </PageDescription>
    <div class="multi-graph-list">
      <div v-for="series in seriesList" :key="series.name" class="single-graph">
        <div class="graph-title">
          {{ series.name }}<span v-if="series.unit"> {{ series.unit }}</span>
          <button class="copy-btn" @click="copyChartImage(series.name)">
            그래프 복사
          </button>
        </div>
        <div
          :ref="el => setGraphRef(series.name, el as Element | null)"
          class="echarts-graph"
        ></div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick } from "vue";
import * as echarts from "echarts";

// 파스텔 컬러 15개 반복
const pastelColors = [
  "#A3D8F4",
  "#F7B7A3",
  "#B5EAD7",
  "#FFDAC1",
  "#C7CEEA",
  "#FFF1BA",
  "#FFB7B2",
  "#B4A7D6",
  "#AED9E0",
  "#FFC3A0",
  "#E2F0CB",
  "#FFB347",
  "#C1C8E4",
  "#FFFACD",
  "#FFD1DC",
];

// 그래프 개수 변수로 분리
const NUM_GRAPHS = 30;

// 30개 y축 정보 (culture-graph.vue와 동일하게 수정)
const yAxisList = [
  { name: "ORP", unit: "", color: pastelColors[0], min: 0, max: 1000 },
  {
    name: "Air flow",
    unit: "(L/min)",
    color: pastelColors[1],
    min: 0,
    max: 30,
  },
  { name: "DO", unit: "", color: pastelColors[2], min: 0, max: 200 },
  { name: "Feed TK1", unit: "(L)", color: pastelColors[3], min: 0, max: 10 },
  { name: "Feed TK2", unit: "(L)", color: pastelColors[4], min: 0, max: 10 },
  { name: "pH", unit: "", color: pastelColors[5], min: 6.0, max: 8.0 },
  { name: "Pressure", unit: "(bar)", color: pastelColors[6], min: 0, max: 2 },
  { name: "RPM", unit: "", color: pastelColors[7], min: 0, max: 3000 },
  { name: "CO2", unit: "(%)", color: pastelColors[8], min: 0, max: 10 },
  { name: "JAR Vol", unit: "(L)", color: pastelColors[9], min: 0, max: 20 },
  { name: "WEIGHT", unit: "(kg)", color: pastelColors[10], min: 0, max: 100 },
  { name: "O2", unit: "(%)", color: pastelColors[11], min: 0, max: 100 },
  { name: "NV", unit: "", color: pastelColors[12], min: 0, max: 10 },
  { name: "NIR", unit: "", color: pastelColors[13], min: 0, max: 10 },
  {
    name: "Temperature",
    unit: "(℃)",
    color: pastelColors[14],
    min: 0,
    max: 50,
  },
  { name: "Humidity", unit: "(%)", color: pastelColors[0], min: 0, max: 100 },
  {
    name: "Flow Rate",
    unit: "(L/min)",
    color: pastelColors[1],
    min: 0,
    max: 60,
  },
  {
    name: "Conductivity",
    unit: "(μS/cm)",
    color: pastelColors[2],
    min: 0,
    max: 600,
  },
  { name: "Turbidity", unit: "(NTU)", color: pastelColors[3], min: 0, max: 12 },
  {
    name: "Dissolved Solids",
    unit: "(mg/L)",
    color: pastelColors[4],
    min: 0,
    max: 250,
  },
  {
    name: "Alkalinity",
    unit: "(mg/L)",
    color: pastelColors[5],
    min: 0,
    max: 120,
  },
  {
    name: "Hardness",
    unit: "(mg/L)",
    color: pastelColors[6],
    min: 0,
    max: 100,
  },
  { name: "Chlorine", unit: "(mg/L)", color: pastelColors[7], min: 0, max: 6 },
  { name: "Nitrate", unit: "(mg/L)", color: pastelColors[8], min: 0, max: 25 },
  {
    name: "Phosphate",
    unit: "(mg/L)",
    color: pastelColors[9],
    min: 0,
    max: 12,
  },
  { name: "Sulfate", unit: "(mg/L)", color: pastelColors[10], min: 0, max: 60 },
  { name: "Ammonia", unit: "(mg/L)", color: pastelColors[11], min: 0, max: 18 },
  { name: "Nitrite", unit: "(mg/L)", color: pastelColors[12], min: 0, max: 6 },
  { name: "BOD", unit: "(mg/L)", color: pastelColors[13], min: 0, max: 35 },
  { name: "COD", unit: "(mg/L)", color: pastelColors[14], min: 0, max: 120 },
];
// NUM_GRAPHS까지 자동 생성
if (yAxisList.length < NUM_GRAPHS) {
  for (let i = yAxisList.length; i < NUM_GRAPHS; i++) {
    yAxisList.push({
      name: `Graph ${i + 1}`,
      unit: "",
      color: pastelColors[i % pastelColors.length],
      min: 0,
      max: 100 + (i % 10) * 100, // 100, 200, ... 1000 반복
    });
  }
}

// x축 간격(초) - 5초 또는 1분(60초) 등으로 변경 가능
// 예시: const X_INTERVAL = 5;   // 5초 간격
//      const X_INTERVAL = 60;  // 1분 간격
const X_INTERVAL = 600; // 필요시 60으로 변경
// 100시간치, X_INTERVAL 간격
const xLabels = Array.from(
  { length: (100 * 60 * 60) / X_INTERVAL + 1 },
  (_, i) => i * X_INTERVAL
);

// 부드러운 곡선형 + 구간별 변화 가데이터 생성 함수 (xLabels를 파라미터로 받도록 변경)
function smoothData(
  min: number,
  max: number,
  xLabels: number[],
  phase = 0,
  _amp = 1, // amp는 사용하지 않으므로 _amp로 변경
  offset = 0,
  seriesIndex: number
) {
  let _prevValue = 0.5;
  const values = [];

  // 데이터 범위 축소: min+10% ~ max-10%
  const rangeMin = min + (max - min) * 0.1;
  const rangeMax = max - (max - min) * 0.1;

  // 시리즈별 패턴 다양화: 증가/감소/진동/트렌드 섞기
  // 패턴 결정 (시리즈 인덱스에 따라)
  const trendType = seriesIndex % 4; // 0:증가, 1:감소, 2:진동, 3:랜덤

  // 진동폭(ampVar, randomFactor)은 원복 (더 낮게)
  const ampVar = 0.2 + (seriesIndex % 5) * 0.1; // 0.2~0.6
  const randomFactor = 0.01 + 0.01 * (seriesIndex % 4); // 0.01~0.04

  for (let i = 0; i < xLabels.length; i++) {
    const t = i / (xLabels.length - 1);
    let base;

    // 오르내림(파동 주기/계수)을 키움 (파동이 더 자주, 더 크게)
    if (trendType === 0) {
      base = 0.2 + 0.6 * t + 0.13 * Math.sin(phase + t * Math.PI * ampVar * 8);
    } else if (trendType === 1) {
      base = 0.8 - 0.6 * t + 0.13 * Math.cos(phase + t * Math.PI * ampVar * 8);
    } else if (trendType === 2) {
      base = 0.5 + 0.22 * Math.sin(phase + t * Math.PI * ampVar * 12);
    } else {
      base = 0.5 + 0.08 * Math.sin(phase + t * Math.PI * ampVar * 6) + 0.2 * t;
    }

    // 노이즈는 낮게
    const noise = (Math.random() - 0.5) * randomFactor;
    base += noise;

    base = Math.max(0, Math.min(1, base));
    const value = +(rangeMin + (rangeMax - rangeMin) * base + offset).toFixed(
      2
    );
    _prevValue = base;

    values.push([xLabels[i], value]);
  }

  return values;
}

// 시리즈 데이터 30개 생성 → 각 그래프마다 12개 라인(시리즈)로 확장
const NUM_LINES_PER_GRAPH = 12;

const seriesList = yAxisList.map((y, idx) => {
  // 12개 라인(시리즈) 생성
  const lines = Array.from({ length: NUM_LINES_PER_GRAPH }, (_, lineIdx) => ({
    name: String(lineIdx + 1), // "1", "2", ... "12"
    color: pastelColors[lineIdx % pastelColors.length],
    data: smoothData(
      y.min,
      y.max,
      xLabels,
      Math.PI / (idx + 1 + lineIdx), // phase를 다르게
      1,
      0,
      idx + lineIdx * 2 // 패턴 다양화
    ),
  }));
  return {
    name: y.name,
    unit: y.unit,
    color: y.color,
    min: y.min,
    max: y.max,
    lines, // 12개 시리즈 배열
  };
});

// 차트 렌더링
const graphRefs = ref<Record<string, HTMLDivElement | null>>({});
const chartInstances = ref<Record<string, echarts.ECharts | null>>({});
function setGraphRef(name: string, el: Element | null) {
  if (el && el instanceof HTMLDivElement) {
    graphRefs.value[name] = el;
  }
}

function renderAllCharts() {
  nextTick(() => {
    seriesList.forEach(series => {
      const el = graphRefs.value[series.name];
      if (!el) return;
      if (chartInstances.value[series.name]) {
        chartInstances.value[series.name]?.dispose();
      }
      const chart = echarts.init(el);
      chart.setOption({
        grid: { left: 50, right: 20, top: 30, bottom: 40, containLabel: true },
        xAxis: {
          type: "value",
          axisLabel: {
            fontSize: 11,
            color: "#666",
            formatter: (v: number) =>
              `${Math.floor(v / 3600)}:${String(Math.floor((v % 3600) / 60)).padStart(2, "0")}`,
          },
        },
        yAxis: {
          type: "value",
          min: series.min,
          max: series.max,
          name: series.unit ? `${series.name} ${series.unit}` : series.name,
          nameTextStyle: {
            color: series.color,
            fontWeight: "bold",
            fontSize: 12,
          },
          axisLabel: { color: series.color, fontWeight: "bold", fontSize: 12 },
          axisLine: { lineStyle: { color: series.color, width: 2 } },
        },
        series: series.lines.map(line => ({
          name: line.name,
          data: line.data,
          type: "line",
          lineStyle: { color: line.color, width: 1 },
          symbol: "none",
        })),
        animation: false,
        legend: {
          show: true,
          bottom: 8, // 하단에 위치
          left: "center", // 중앙 정렬
          orient: "horizontal",
          itemWidth: 18,
          itemHeight: 10,
          icon: "circle",
          textStyle: { fontSize: 12, padding: [0, 4, 0, 0] },
        },
        tooltip: { show: true, trigger: "axis" },
      });
      chartInstances.value[series.name] = chart;
    });
  });
}

// 이미지 복사 함수 추가
async function copyImageToClipboard(dataUrl: string) {
  const res = await fetch(dataUrl);
  const blob = await res.blob();
  await navigator.clipboard.write([
    new window.ClipboardItem({ [blob.type]: blob }),
  ]);
}

async function copyChartImage(name: string) {
  const chart = chartInstances.value[name];
  if (!chart) return;
  const dataUrl = chart.getDataURL({
    type: "png",
    pixelRatio: 2,
    backgroundColor: "#fff",
  });
  try {
    await copyImageToClipboard(dataUrl);
    alert("그래프가 클립보드에 복사되었습니다!");
  } catch {
    alert("클립보드 복사에 실패했습니다. 브라우저 권한을 확인하세요.");
  }
}

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

<style scoped>
.multi-graph-list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px 1.5%;
  padding: 16px 0;
  align-content: flex-start;
  flex-direction: row;
  background: #fff;
}
.single-graph {
  min-height: 260px;
  width: 100%;
  flex: 0 0 100%;
  max-width: 100%;
  background: #fff;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  padding: 10px 16px 10px 16px;
  position: relative;
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;
  align-items: flex-start;
}
.graph-title {
  font-weight: bold;
  font-size: 1.05rem;
  color: #1976d2;
  margin-bottom: 6px;
  width: 100%;
}
.echarts-graph {
  min-height: 200px;
  height: 200px !important;
  width: 100%;
}
.copy-btn {
  margin-left: 10px;
  font-size: 0.9rem;
  padding: 2px 8px;
  border: 1px solid #1976d2;
  background: #e3f2fd;
  color: #1976d2;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.2s;
  float: right;
}
.copy-btn:hover {
  background: #bbdefb;
}
</style>
