import {
  AfterViewInit,
  Component,
  ElementRef,
  Input,
  OnChanges,
  OnDestroy,
  SimpleChanges,
  ViewChild,
} from '@angular/core';
import {
  Chart,
  ChartConfiguration,
  ChartData,
  ChartOptions,
  ChartType,
  registerables,
} from 'chart.js';

Chart.register(...registerables);

/**
 * Thin wrapper around a Chart.js instance bound to a `<canvas>`. Chart-specific
 * configuration (labels, datasets, colors, ...) is built by the caller and passed
 * in via inputs — this component only manages the Chart.js instance lifecycle.
 */
@Component({
  selector: 'app-chart-canvas',
  templateUrl: './chart-canvas.html',
  styleUrl: './chart-canvas.scss',
})
export class ChartCanvas implements AfterViewInit, OnChanges, OnDestroy {
  @Input({ required: true }) type!: ChartType;
  @Input({ required: true }) data!: ChartData;
  @Input() options?: ChartOptions;

  @ViewChild('canvas', { static: true })
  private readonly canvasRef!: ElementRef<HTMLCanvasElement>;

  private chart?: Chart;

  ngAfterViewInit(): void {
    this.createChart();
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (!this.chart) {
      // Initial creation is handled by ngAfterViewInit once the canvas exists.
      return;
    }

    if (changes['type'] && !changes['type'].firstChange) {
      this.chart.destroy();
      this.createChart();
      return;
    }

    if (changes['data']) {
      this.chart.data = this.data;
    }
    if (changes['options']) {
      this.chart.options = this.options ?? {};
    }
    if (changes['data'] || changes['options']) {
      this.chart.update();
    }
  }

  ngOnDestroy(): void {
    this.chart?.destroy();
  }

  private createChart(): void {
    const config = {
      type: this.type,
      data: this.data,
      options: this.options,
    } as ChartConfiguration;
    this.chart = new Chart(this.canvasRef.nativeElement, config);
  }
}
