<template>
  <section class="admin-chart-block">
    <header class="admin-chart-block__header">
      <div>
        <span>Data insight</span>
        <h3>{{ display.title || ${chartInstanceNameJson} }}</h3>
      </div>
      <el-button type="text" icon="el-icon-refresh" :disabled="loading" @click="retry">Refresh</el-button>
    </header>

    <el-skeleton v-if="loading" :rows="5" animated />

    <div v-else-if="errorMessage" class="admin-chart-block__error">
      <el-alert :title="errorMessage" type="error" :closable="false" show-icon />
      <el-button size="small" type="primary" plain @click="retry">Retry</el-button>
    </div>

    <el-empty v-else-if="!hasData" description="No chart data" />

    <div v-else-if="chartType === 'metric'" class="admin-chart-block__metric">
      <strong>{{ metricValue }}</strong>
      <span>{{ display.subtitle || display.unit || "" }}</span>
    </div>

    <div v-else ref="chart" class="admin-chart-block__chart"></div>
  </section>
</template>

<script>
import { load${InstanceClassName}Data } from "${apiModulePath}"
import { buildChartOption, createChart, hasChartData } from "@/utils/chartRuntime"

export default {
  name: "${InstanceClassName}",
  data() {
    return {
      chartType: "${chartType}",
      display: ${chartDisplayJson},
      loading: false,
      errorMessage: "",
      payload: null,
      chart: null
    }
  },
  computed: {
    hasData() {
      return hasChartData(this.payload)
    },
    metricValue() {
      const summary = this.payload && this.payload.summary
      return summary && summary.value !== null && summary.value !== undefined
        ? summary.value
        : "-"
    }
  },
  created() {
    this.loadData()
  },
  mounted() {
    window.addEventListener("resize", this.handleResize)
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.handleResize)
    this.disposeChart()
  },
  methods: {
    loadData() {
      this.disposeChart()
      this.loading = true
      this.errorMessage = ""
      return load${InstanceClassName}Data()
        .then(response => {
          this.payload = (response && response.data) || null
          this.loading = false
          if (this.chartType === "metric" || !this.hasData) {
            this.disposeChart()
            return
          }
          this.#[[$nextTick]]#(() => this.renderChart())
        })
        .catch(error => {
          this.loading = false
          this.payload = null
          this.errorMessage = error && error.message ? error.message : "Failed to load chart data"
          this.disposeChart()
        })
    },
    retry() {
      return this.loadData()
    },
    renderChart() {
      if (!this.#[[$refs]]#.chart) {
        return
      }
      if (!this.chart) {
        this.chart = createChart(this.#[[$refs]]#.chart)
      }
      this.chart.setOption(buildChartOption(this.chartType, this.display, this.payload), true)
    },
    handleResize() {
      if (this.chart) {
        this.chart.resize()
      }
    },
    disposeChart() {
      if (this.chart) {
        this.chart.dispose()
        this.chart = null
      }
    }
  }
}
</script>

<style scoped>
.admin-chart-block {
  min-height: 320px;
  padding: 20px;
  background: #fff;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  box-sizing: border-box;
}

.admin-chart-block__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.admin-chart-block__header span {
  color: #409eff;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
}

.admin-chart-block__header h3 {
  margin: 4px 0 0;
  color: #303133;
  font-size: 18px;
}

.admin-chart-block__chart {
  width: 100%;
  height: 250px;
}

.admin-chart-block__metric {
  display: flex;
  min-height: 220px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.admin-chart-block__metric strong {
  color: #303133;
  font-size: 48px;
  line-height: 1;
}

.admin-chart-block__metric span {
  color: #909399;
}

.admin-chart-block__error {
  display: grid;
  min-height: 220px;
  align-content: center;
  gap: 16px;
}
</style>
