import jsPDF from "jspdf";

export interface ChartData {
  labels: string[];
  datasets: {
    label: string;
    data: number[];
    color?: string;
  }[];
}

export interface ChartConfig {
  title?: string;
  width: number;
  height: number;
}

/**
 * Generate a bar chart image as a data URL
 */
export function generateBarChart(data: ChartData, config: ChartConfig): string {
  const canvas = createCanvas(config.width, config.height);
  const ctx = canvas.getContext("2d");

  if (!ctx) {
    throw new Error("Could not get canvas context");
  }

  const padding = 40;
  const chartWidth = config.width - padding * 2;
  const chartHeight = config.height - padding * 2;
  const barWidth = chartWidth / data.labels.length - 10;

  // Clear canvas
  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, config.width, config.height);

  // Add title if provided
  if (config.title) {
    ctx.fillStyle = "#000000";
    ctx.font = "bold 14px Arial";
    ctx.textAlign = "center";
    ctx.fillText(config.title, config.width / 2, 20);
  }

  // Calculate max value
  const maxValue = Math.max(
    ...data.datasets.flatMap((dataset) => dataset.data),
  );

  // Draw bars
  data.datasets.forEach((dataset, datasetIndex) => {
    const color = dataset.color || getDefaultColor(datasetIndex);
    ctx.fillStyle = color;

    dataset.data.forEach((value, index) => {
      const x =
        padding +
        index * (barWidth + 10) +
        (datasetIndex * barWidth) / data.datasets.length;
      const barHeight = (value / maxValue) * chartHeight;
      const y = config.height - padding - barHeight;

      ctx.fillRect(x, y, barWidth / data.datasets.length - 2, barHeight);

      // Draw value on top
      ctx.fillStyle = "#000000";
      ctx.font = "10px Arial";
      ctx.textAlign = "center";
      ctx.fillText(
        value.toString(),
        x + barWidth / data.datasets.length / 2,
        y - 5,
      );
      ctx.fillStyle = color;
    });
  });

  // Draw labels
  ctx.fillStyle = "#000000";
  ctx.font = "11px Arial";
  ctx.textAlign = "center";
  data.labels.forEach((label, index) => {
    const x = padding + index * (barWidth + 10) + barWidth / 2;
    ctx.fillText(label, x, config.height - padding + 15);
  });

  // Draw axes
  ctx.strokeStyle = "#cccccc";
  ctx.beginPath();
  ctx.moveTo(padding, padding);
  ctx.lineTo(padding, config.height - padding);
  ctx.lineTo(config.width - padding, config.height - padding);
  ctx.stroke();

  return canvas.toDataURL("image/png");
}

/**
 * Generate a line chart image as a data URL
 */
export function generateLineChart(
  data: ChartData,
  config: ChartConfig,
): string {
  const canvas = createCanvas(config.width, config.height);
  const ctx = canvas.getContext("2d");

  if (!ctx) {
    throw new Error("Could not get canvas context");
  }

  const padding = 40;
  const chartWidth = config.width - padding * 2;
  const chartHeight = config.height - padding * 2;

  // Clear canvas
  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, config.width, config.height);

  // Add title if provided
  if (config.title) {
    ctx.fillStyle = "#000000";
    ctx.font = "bold 14px Arial";
    ctx.textAlign = "center";
    ctx.fillText(config.title, config.width / 2, 20);
  }

  // Calculate max value
  const maxValue = Math.max(
    ...data.datasets.flatMap((dataset) => dataset.data),
    1,
  );

  // Draw grid lines
  ctx.strokeStyle = "#f0f0f0";
  ctx.lineWidth = 1;
  for (let i = 0; i <= 5; i++) {
    const y = padding + (i * chartHeight) / 5;
    ctx.beginPath();
    ctx.moveTo(padding, y);
    ctx.lineTo(config.width - padding, y);
    ctx.stroke();

    // Draw value labels
    ctx.fillStyle = "#666666";
    ctx.font = "10px Arial";
    ctx.textAlign = "right";
    const value = Math.round(maxValue - (i * maxValue) / 5);
    ctx.fillText(value.toString(), padding - 5, y + 3);
  }

  // Draw lines
  data.datasets.forEach((dataset, datasetIndex) => {
    const color = dataset.color || getDefaultColor(datasetIndex);
    ctx.strokeStyle = color;
    ctx.lineWidth = 2;
    ctx.beginPath();

    dataset.data.forEach((value, index) => {
      const x = padding + (index * chartWidth) / (data.labels.length - 1);
      const y = config.height - padding - (value / maxValue) * chartHeight;

      if (index === 0) {
        ctx.moveTo(x, y);
      } else {
        ctx.lineTo(x, y);
      }
    });

    ctx.stroke();

    // Draw points
    ctx.fillStyle = color;
    dataset.data.forEach((value, index) => {
      const x = padding + (index * chartWidth) / (data.labels.length - 1);
      const y = config.height - padding - (value / maxValue) * chartHeight;

      ctx.beginPath();
      ctx.arc(x, y, 4, 0, 2 * Math.PI);
      ctx.fill();
    });
  });

  // Draw labels
  ctx.fillStyle = "#000000";
  ctx.font = "11px Arial";
  ctx.textAlign = "center";
  data.labels.forEach((label, index) => {
    const x = padding + (index * chartWidth) / (data.labels.length - 1);
    ctx.fillText(label, x, config.height - padding + 15);
  });

  // Draw axes
  ctx.strokeStyle = "#cccccc";
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(padding, padding);
  ctx.lineTo(padding, config.height - padding);
  ctx.lineTo(config.width - padding, config.height - padding);
  ctx.stroke();

  return canvas.toDataURL("image/png");
}

/**
 * Generate a pie chart image as a data URL
 */
export function generatePieChart(data: ChartData, config: ChartConfig): string {
  const canvas = createCanvas(config.width, config.height);
  const ctx = canvas.getContext("2d");

  if (!ctx) {
    throw new Error("Could not get canvas context");
  }

  const centerX = config.width / 2;
  const centerY = config.height / 2;
  const radius = Math.min(config.width, config.height) / 2 - 40;

  // Clear canvas
  ctx.fillStyle = "#ffffff";
  ctx.fillRect(0, 0, config.width, config.height);

  // Add title if provided
  if (config.title) {
    ctx.fillStyle = "#000000";
    ctx.font = "bold 14px Arial";
    ctx.textAlign = "center";
    ctx.fillText(config.title, config.width / 2, 20);
  }

  // Calculate total
  const total = data.datasets[0]?.data.reduce((sum, val) => sum + val, 0) || 0;

  // Draw pie slices
  let startAngle = 0;
  data.datasets[0]?.data.forEach((value, index) => {
    const sliceAngle = (value / total) * 2 * Math.PI;
    const color = data.datasets[0].color || getDefaultColor(index);

    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.moveTo(centerX, centerY);
    ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle);
    ctx.closePath();
    ctx.fill();

    // Draw label
    const midAngle = startAngle + sliceAngle / 2;
    const labelX = centerX + (radius + 20) * Math.cos(midAngle);
    const labelY = centerY + (radius + 20) * Math.sin(midAngle);

    ctx.fillStyle = "#000000";
    ctx.font = "11px Arial";
    ctx.textAlign = "center";
    ctx.fillText(`${data.labels[index]}: ${value}`, labelX, labelY);

    startAngle += sliceAngle;
  });

  return canvas.toDataURL("image/png");
}

/**
 * Helper function to create a canvas element
 */
function createCanvas(width: number, height: number): HTMLCanvasElement {
  if (typeof document !== "undefined") {
    const canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    return canvas;
  }
  // Fallback for server-side rendering
  const Canvas = require("canvas");
  return new Canvas(width, height);
}

/**
 * Get default color for a dataset index
 */
function getDefaultColor(index: number): string {
  const colors = [
    "#3c82e1", // primary
    "#2ea643", // success
    "#f0a500", // warning
    "#d73232", // destructive
    "#8b5cf6", // purple
    "#06b6d4", // cyan
  ];
  return colors[index % colors.length];
}

/**
 * Add chart image to PDF
 */
export function addChartToPDF(
  pdf: jsPDF,
  imageData: string,
  x: number,
  y: number,
  width?: number,
  height?: number,
): void {
  const imgWidth = width || 150;
  const imgHeight = height || 80;
  pdf.addImage(imageData, "PNG", x, y, imgWidth, imgHeight);
}

export default {
  generateBarChart,
  generateLineChart,
  generatePieChart,
  addChartToPDF,
};
