<template>
  <div class="trend-chart">
    <canvas
      ref="chartCanvas"
      :width="width"
      :height="height"
      class="chart-canvas"
    ></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from "vue";
import {
  Chart,
  CategoryScale,
  LinearScale,
  LineElement,
  PointElement,
  BarElement,
  LineController,
  BarController,
  Title,
  Tooltip,
  Legend,
  Filler,
} from "chart.js";

// Register Chart.js components
Chart.register(
  CategoryScale,
  LinearScale,
  LineElement,
  PointElement,
  BarElement,
  LineController,
  BarController,
  Title,
  Tooltip,
  Legend,
  Filler,
);

// Props definition
const props = defineProps({
  data: {
    type: Object,
    required: true,
    default: () => ({
      labels: [],
      datasets: [],
    }),
  },
  type: {
    type: String,
    default: "line",
    validator: (value) => ["line", "bar", "area"].includes(value),
  },
  compare: {
    type: Boolean,
    default: false,
  },
  width: {
    type: Number,
    default: 400,
  },
  height: {
    type: Number,
    default: 200,
  },
  options: {
    type: Object,
    default: () => ({}),
  },
});

// Refs
const chartCanvas = ref(null);
const chartInstance = ref(null);

// Romanian currency formatter
const formatCurrency = (value) => {
  return new Intl.NumberFormat("ro-RO", {
    style: "currency",
    currency: "RON",
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  }).format(value);
};

// Chart configuration
const getChartConfig = () => {
  const chartType = props.type === "area" ? "line" : props.type;

  const config = {
    type: chartType,
    data: {
      labels: props.data.labels || [],
      datasets: (props.data.datasets || []).map((dataset, index) => {
        const baseConfig = {
          ...dataset,
          borderWidth: props.type === "line" || props.type === "area" ? 2 : 0,
          pointBackgroundColor: dataset.borderColor || dataset.backgroundColor,
          pointBorderColor: dataset.borderColor || dataset.backgroundColor,
          pointRadius: props.type === "line" || props.type === "area" ? 4 : 0,
          pointHoverRadius:
            props.type === "line" || props.type === "area" ? 6 : 0,
        };

        // Area chart specific configuration
        if (props.type === "area") {
          baseConfig.fill = true;
          baseConfig.backgroundColor =
            dataset.backgroundColor ||
            (dataset.borderColor
              ? dataset.borderColor
                  .replace("rgb", "rgba")
                  .replace(")", ", 0.1)")
              : "rgba(54, 162, 235, 0.1)");
        }

        // Bar chart specific configuration
        if (props.type === "bar") {
          baseConfig.borderRadius = 4;
          baseConfig.borderSkipped = false;
        }

        return baseConfig;
      }),
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          display: props.compare,
          position: "top",
          labels: {
            usePointStyle: true,
            padding: 20,
            font: {
              size: 12,
            },
          },
        },
        tooltip: {
          mode: "index",
          intersect: false,
          callbacks: {
            label: function (context) {
              let label = context.dataset.label || "";
              if (label) {
                label += ": ";
              }
              if (context.parsed.y !== null) {
                label += formatCurrency(context.parsed.y);
              }
              return label;
            },
          },
          backgroundColor: "rgba(0, 0, 0, 0.8)",
          titleColor: "#fff",
          bodyColor: "#fff",
          borderColor: "rgba(255, 255, 255, 0.1)",
          borderWidth: 1,
        },
      },
      scales: {
        x: {
          display: true,
          grid: {
            display: false,
          },
          ticks: {
            font: {
              size: 11,
            },
            color: "#6b7280",
          },
        },
        y: {
          display: true,
          beginAtZero: true,
          grid: {
            color: "rgba(0, 0, 0, 0.05)",
          },
          ticks: {
            font: {
              size: 11,
            },
            color: "#6b7280",
            callback: function (value) {
              return formatCurrency(value);
            },
          },
        },
      },
      interaction: {
        mode: "index",
        intersect: false,
      },
      hover: {
        mode: "index",
        intersect: false,
      },
      // Merge with custom options
      ...props.options,
    },
  };

  return config;
};

// Create chart instance
const createChart = () => {
  if (!chartCanvas.value) return;

  const config = getChartConfig();

  // Deep clone the entire config to break Vue reactivity circular references
  const clonedConfig = JSON.parse(JSON.stringify(config));

  chartInstance.value = new Chart(chartCanvas.value, clonedConfig);
};

// Destroy chart instance
const destroyChart = () => {
  if (chartInstance.value) {
    chartInstance.value.destroy();
    chartInstance.value = null;
  }
};

// Update chart data
const updateChart = () => {
  if (!chartInstance.value) return;

  const config = getChartConfig();

  // Deep clone the data to break Vue reactivity circular references
  const clonedData = JSON.parse(JSON.stringify(config.data));

  // Update data
  chartInstance.value.data = clonedData;

  // Update options (clone options too to be safe)
  chartInstance.value.options = JSON.parse(JSON.stringify(config.options));

  // Re-render
  chartInstance.value.update("none");
};

// Recreate chart completely
const recreateChart = async () => {
  destroyChart();
  await nextTick();
  createChart();
};

// Watch for prop changes
watch(
  () => [props.data, props.type, props.compare, props.options],
  async (newValues, oldValues) => {
    // Skip if chart is not initialized
    if (!chartInstance.value) return;

    // If chart type changed, recreate completely
    if (newValues[1] !== oldValues[1]) {
      await recreateChart();
    } else {
      // Otherwise just update
      updateChart();
    }
  },
  { deep: true },
);

// Lifecycle hooks
onMounted(() => {
  nextTick(() => {
    createChart();
  });
});

onBeforeUnmount(() => {
  destroyChart();
});

// Expose methods for parent components
defineExpose({
  updateChart,
  recreateChart,
  chartInstance: () => chartInstance.value,
});
</script>

<style scoped>
.trend-chart {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 200px;
}

.chart-canvas {
  width: 100% !important;
  height: 100% !important;
}

/* Responsive adjustments */
@media (max-width: 768px) {
  .trend-chart {
    min-height: 150px;
  }
}

@media (max-width: 480px) {
  .trend-chart {
    min-height: 120px;
  }
}
</style>
