<template>
  <div v-bind="$attrs" class="chart-wrapper full-width full-height">
    <q-resize-observer @resize="onResize" />
    <div v-if="hasData" class="chart-container">
      <Bar
        ref="chart_ref"
        :options="chartOptions"
        :data="chartData"
        :plugins="activePlugins"
      />
    </div>
    <div v-else class="no-data-container">
      <span class="text-grey-6">{{ $t("http.errors.no_records_found") }}</span>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from "vue";
import { Bar } from "vue-chartjs";
import {
  Chart as ChartJS,
  Title,
  Tooltip,
  Legend,
  BarElement,
  CategoryScale,
  LinearScale,
} from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { base64ToJPEG } from "src/helpers/convertBase64Image";

ChartJS.register(
  Title,
  Tooltip,
  Legend,
  BarElement,
  CategoryScale,
  LinearScale,
);

const chart_ref = ref(null);

const props = defineProps({
  labels: {
    type: Array,
    default: () => [],
  },
  datasets: {
    type: Array,
    default: () => [],
  },
  title: {
    type: String,
    default: "",
  },
  labelY: {
    type: String,
    default: "",
  },
  barRadius: {
    type: Number,
    default: 4,
  },
  showDatalabels: {
    type: Boolean,
    default: false,
  },
  tickFormatter: {
    type: Function,
    default: null,
  },
  tooltipFormatter: {
    type: Function,
    default: null,
  },
  maxBarThickness: {
    type: Number,
    default: null,
  },
  categoryPercentage: {
    type: Number,
    default: 0.8,
  },
  barPercentage: {
    type: Number,
    default: 0.9,
  },
});

const onResize = () => {
  if (chart_ref.value?.chart) {
    setTimeout(() => chart_ref.value.chart.resize(), 50);
  }
};

const hasData = computed(
  () => props.labels.length > 0 && props.datasets.length > 0,
);

const activePlugins = computed(() => [ChartDataLabels]);

const chartData = computed(() => ({
  labels: props.labels,
  datasets: props.datasets.map((ds) => ({
    label: ds.label,
    data: ds.data,
    backgroundColor: ds.color,
    borderColor: ds.color,
    borderRadius: props.barRadius,
    borderSkipped: false,
    borderWidth: 0,
    ...(props.maxBarThickness != null
      ? { maxBarThickness: props.maxBarThickness }
      : {}),
    categoryPercentage: props.categoryPercentage,
    barPercentage: props.barPercentage,
  })),
}));

const labelColor = "#555555";
const gridColor = "rgba(0,0,0,0.07)";

const chartOptions = computed(() => ({
  responsive: true,
  maintainAspectRatio: false,
  layout: {
    padding: {
      top: props.showDatalabels ? 28 : 8,
      left: 12,
      right: 12,
      bottom: 4,
    },
  },
  plugins: {
    legend: {
      display: false,
    },
    datalabels: {
      display: props.showDatalabels,
      anchor: "end",
      align: "top",
      offset: 4,
      color: "#333",
      font: { size: 12, weight: "bold" },
      formatter: (v) => (v > 0 ? v : ""),
    },
    tooltip: {
      backgroundColor: "rgba(255,255,255,0.95)",
      titleColor: "#333",
      bodyColor: "#555",
      borderColor: "rgba(0,0,0,0.1)",
      borderWidth: 1,
      callbacks: props.tooltipFormatter
        ? { label: props.tooltipFormatter }
        : {},
    },
  },
  scales: {
    x: {
      grid: { display: false },
      ticks: { color: labelColor, font: { size: 11 } },
    },
    y: {
      display: true,
      title: {
        display: !!props.labelY,
        text: props.labelY,
        color: labelColor,
        font: { size: 12 },
      },
      grid: { color: gridColor },
      ticks: {
        color: labelColor,
        font: { size: 11 },
        callback: props.tickFormatter ?? ((v) => v),
      },
      suggestedMin: 0,
    },
  },
}));

const downloadImage = () => {
  const image = chart_ref.value?.chart?.toBase64Image("image/jpeg", 1);
  if (image) base64ToJPEG(image, props.title || "grouped-bar-chart");
};

defineExpose({ downloadImage, chart_ref });
</script>

<style scoped>
.chart-wrapper {
  position: relative;
}

.chart-container {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

.no-data-container {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}
</style>
