import {
  Component,
  ChangeDetectionStrategy,
  viewChild,
  input, computed, signal, effect,
} from '@angular/core';
import {BaseChartDirective} from 'ng2-charts';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {
  ChartData,
  ChartOptions,
  ChartType,
  Plugin, TooltipItem
} from 'chart.js';
import 'chartjs-adapter-date-fns';
import {fileSizeConfigCount} from '@common/shared/pipes/filesize.pipe';
import {filesize} from 'filesize';


declare module 'chart.js' {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  interface PluginOptionsByType<TType extends ChartType> {
    hoverLine?: {
      color?: string;
      dash?: [number, number];
      width?: number;
      drawY?: boolean;
    }
  }
}


interface Topic {
  topicName: string;
  topic: number;
  dates: { value: number; date: string }[];
}

export interface concatLatestFrom {
  dataByTopic?: Topic[];
}

@Component({
  selector       : 'sm-line-chart',
  templateUrl    : './line-chart.component.html',
  styleUrls      : ['./line-chart.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [
    BaseChartDirective,
    MatProgressSpinnerModule
  ]
})
export class LineChartComponent {
  lineChartPlugins: Plugin<'line'>[] =  [{
    id: 'hoverLine',
    afterDatasetsDraw: (chart, _, opts) => {
      const {
        ctx,
        tooltip,
        chartArea: { top, bottom}
      } = chart;

      if (tooltip.opacity) {
        ctx.lineWidth = opts.width || 0;
        ctx.setLineDash(opts.dash || []);
        ctx.strokeStyle = opts.color || 'black';

        ctx.save();
        ctx.beginPath();
        ctx.moveTo(tooltip.caretX, bottom);
        ctx.lineTo(tooltip.caretX, top);
        ctx.stroke();
        ctx.closePath();
        ctx.setLineDash([]);
      }
    }
  }];
  public lineChartType: ChartType = 'line';

  private chart = viewChild(BaseChartDirective);
  animationDuration = signal(500);

  colorScheme= input(['#a4a1fb', '#ff8a15']);
  yTickFormatter = input<(value: number) => string>(val => filesize(val, fileSizeConfigCount));
  yLabel = input<string>();
  showLoadingOverlay = input(false);
  data = input<Topic[]>();

  chartData = computed<ChartData<'line', Topic['dates']>>(() => {
    const topics = this.data();
    if (topics && !(topics?.length > 0)) {
      return null;
    }

    return {
      datasets: topics?.map((topic, index) => this.createDataset(topic, index)) ?? [],
    };
  });

  lineChartOptions = computed(() => ({
    animation: {
      duration: this.animationDuration(),
    },
    maintainAspectRatio: false,
    layout: {
      padding: {top: 12, bottom: 12}
    },
    elements: {
      line: {
        tension: 0.5,
      },
    },
    interaction: {
      intersect: false,
      mode: 'index',
    },
    scales: {
      x: {
        type: 'time',
        ticks: {
          autoSkip: true,
          autoSkipPadding: 50,
          maxRotation: 0,
          color: '#c1cdf3',
        },
        time: {
          tooltipFormat: 'P pp',
          displayFormats: {
            month: 'MMM yyyy',
            day: 'dd MMM',
            hour: 'E p',
            minute: 'p',
            second: 'pp'
          }
        },
      },
      y: {
        title: {display: !!this.yLabel(), text: this.yLabel(), color: '#c1cdf3'},
        position: 'left',
        suggestedMin: 0,
        beginAtZero: true,
        ticks: {
          autoSkip: true,
          count: 5,
          precision: 0,
          color: '#c1cdf3',
          callback: value => typeof value === 'number' ? this.yTickFormatter()(value) : value
        },
        grid: {
          display: true,
          color: '#39405f',
        }
      },
    },

    plugins: {
      legend: {
        display: true,
        position: 'bottom',
        labels: {
          color: '#dce0ee',
          font: {weight: 'normal', size: 12},
          padding: 20,
          usePointStyle: true,
        }

      },
      tooltip: {
        backgroundColor: '#1a1e2c',
        borderWidth: 1,
        borderColor: '#8492c2',
        bodyColor: '#c3cdf0',
        bodyFont: {weight: 'normal', size: 12},
        padding: 12,
        usePointStyle: true,
        callbacks: {
          label: (item: TooltipItem<'line'>) => `${item.dataset.label}: ${this.yTickFormatter()((item.dataset.data[item.dataIndex] as unknown as Topic['dates'][0]).value)}`
        }
      },
      hoverLine: {
        dash: [6, 6],
        color: '#8492c2',
        width: 1,
      },
    },

    parsing: {
      xAxisKey: 'date',
      yAxisKey: 'value'
    }
  } as ChartOptions<'line'>))
  private createDataset(topic: Topic, index: number) {
    return {
      data: topic.dates,
      label: topic.topicName,
      pointRadius: 0,
      pointBorderColor: '#1a1e2c',
      borderWidth: 2,
      lineTension: 0.1,
      pointBackgroundColor: this.colorScheme()[index % this.colorScheme.length],
      borderColor: this.colorScheme()[index % this.colorScheme().length],
      backgroundColor: this.colorScheme()[index % this.colorScheme().length]
    };
  }


  constructor() {
    effect(() => {
      if (this.data()?.[0]?.dates.length > 0) {
        this.animationDuration.set(0);
        this.chart().update();
      }
    }, {allowSignalWrites: true});
  }
}
