import {
  DeesElement,
  css,
  cssManager,
  customElement,
  html,
  property,
  state,
  type CSSResult,
  type TemplateResult,
} from '@design.estate/dees-element';

import * as domtools from '@design.estate/dees-domtools';
import { demoFunc } from './dees-chart-area.demo.js';

import ApexCharts from 'apexcharts';

declare global {
  interface HTMLElementTagNameMap {
    'dees-chart-area': DeesChartArea;
  }
}

@customElement('dees-chart-area')
export class DeesChartArea extends DeesElement {
  public static demo = demoFunc;

  // instance
  @state()
  public chart: ApexCharts;

  @property()
  public label: string = 'Untitled Chart';

  private resizeObserver: ResizeObserver;

  constructor() {
    super();
    domtools.elementBasic.setup();

    this.resizeObserver = new ResizeObserver((entries) => {
      for (let entry of entries) {
        if (entry.target.classList.contains('mainbox')) {
          this.resizeChart(); // Call resizeChart when the .mainbox size changes
        }
      }
    });
    this.registerStartupFunction(async () => {
      this.updateComplete.then(() => {
        const mainbox = this.shadowRoot.querySelector('.mainbox');
        if (mainbox) {
          this.resizeObserver.observe(mainbox); // Start observing the .mainbox element
        }
      });
    });
    this.registerGarbageFunction(async () => {
      this.resizeObserver.disconnect();
    });
  }

  public static styles = [
    cssManager.defaultStyles,
    css`
      :host {
        font-family: 'Geist Sans', sans-serif;
        color: #ccc;
        font-weight: 600;
        font-size: 12px;
      }
      .mainbox {
        position: relative;
        width: 100%;
        height: 400px;
        background: #111;
        border-radius: 8px;
      }

      .chartTitle {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        text-align: center;
        padding-top: 16px;
      }
      .chartContainer {
        position: absolute;
        top: 0px;
        left: 0px;
        bottom: 0px;
        right: 0px;
        padding: 32px 16px 16px 0px;
      }
    `,
  ];

  public render(): TemplateResult {
    return html`
      <div class="mainbox">
        <div class="chartTitle">${this.label}</div>
        <div class="chartContainer"></div>
      </div>
    `;
  }

  public async firstUpdated() {
    const domtoolsInstance = await this.domtoolsPromise;
    var options: ApexCharts.ApexOptions = {
      series: [
        {
          name: 'cpu',
          data: [
            { x: '2025-01-15T03:00:00', y: 25 },
            { x: '2025-01-15T07:00:00', y: 30 },
            { x: '2025-01-15T11:00:00', y: 20 },
            { x: '2025-01-15T15:00:00', y: 35 },
            { x: '2025-01-15T19:00:00', y: 25 },
          ],
        },
        {
          name: 'memory',
          data: [
            { x: '2025-01-15T03:00:00', y: 10 },
            { x: '2025-01-15T07:00:00', y: 12 },
            { x: '2025-01-15T11:00:00', y: 10 },
            { x: '2025-01-15T15:00:00', y: 30 },
            { x: '2025-01-15T19:00:00', y: 40 },
          ],
        },
      ],
      chart: {
        width: 0, // Adjusted for responsive width
        height: 0, // Adjusted for responsive height
        type: 'area',
        toolbar: {
          show: false, // This line disables the toolbar
        },
      },
      dataLabels: {
        enabled: false,
      },
      stroke: {
        width: 1,
        curve: 'smooth',
      },
      xaxis: {
        type: 'datetime', // Time-series data
        labels: {
          format: 'hh:mm A', // Time formatting
          style: {
            colors: '#9e9e9e', // Label color
            fontSize: '12px',
          },
        },
        axisBorder: {
          show: false, // Hide x-axis border
        },
        axisTicks: {
          show: false, // Hide x-axis ticks
        },
      },
      yaxis: {
        min: 0,
        labels: {
          formatter: function (val: number) {
            return `${val} Mbps`; // Format Y-axis labels
          },
          style: {
            colors: '#9e9e9e', // Label color
            fontSize: '12px',
          },
        },
        axisBorder: {
          show: false, // Hide y-axis border
        },
        axisTicks: {
          show: false, // Hide y-axis ticks
        },
      },
      tooltip: {
        shared: true, // Enables the tooltip to display across series
        intersect: false, // Allows hovering anywhere on the chart
        followCursor: true, // Makes tooltip follow mouse even between points
        x: {
          format: 'dd/MM/yy HH:mm',
        },
        custom: function ({ series, seriesIndex, dataPointIndex, w }) {
          // Get the x value
          const xValue = w.globals.labels[dataPointIndex];
          // Iterate through each series and get its value
          let tooltipContent = `<div style="padding: 10px; background: #1e1e2f; color: white; border-radius: 5px;">`;
          tooltipContent += ``; // `<strong>Time:</strong> ${xValue}<br/>`;

          series.forEach((s, index) => {
            const label = w.globals.seriesNames[index]; // Get series label
            const value = s[dataPointIndex]; // Get value at data point
            tooltipContent += `<strong>${label}:</strong> ${value} Mbps<br/>`;
          });

          tooltipContent += `</div>`;
          return tooltipContent;
        },
      },
      grid: {
        xaxis: {
          lines: {
            show: true, // This enables the grid lines along the x-axis
          },
        },
        yaxis: {
          lines: {
            show: true,
          },
        },
        borderColor: '#333', // Set the color of the grid lines
        strokeDashArray: 0, // Solid line
        row: {
          colors: [], // This can be used to alternate the shading of the horizontal rows
          opacity: 0.1,
        },
        column: {
          colors: [], // For vertical column bands, not needed here but available for customization
          opacity: 0.1,
        },
      },
      fill: {
        type: 'gradient', // Gradient fill for the area
        gradient: {
          shade: 'dark',
          type: 'vertical',
          gradientToColors: ['#9c27b0'], // Gradient color ending
          stops: [0, 100],
        },
      },
    };
    this.chart = new ApexCharts(this.shadowRoot.querySelector('.chartContainer'), options);
    await this.chart.render();
    await this.resizeChart();
  }

  public async resizeChart() {
    const mainbox: HTMLDivElement = this.shadowRoot.querySelector('.mainbox');
    const chartContainer: HTMLDivElement = this.shadowRoot.querySelector('.chartContainer');

    // Get computed style of the element
    const styleMainbox = window.getComputedStyle(mainbox);
    const styleChartContainer = window.getComputedStyle(chartContainer);

    // Extract padding values
    const paddingTop = parseInt(styleChartContainer.paddingTop, 10);
    const paddingBottom = parseInt(styleChartContainer.paddingBottom, 10);
    const paddingLeft = parseInt(styleChartContainer.paddingLeft, 10);
    const paddingRight = parseInt(styleChartContainer.paddingRight, 10);

    // Calculate the actual width and height to use, subtracting padding
    const actualWidth = mainbox.clientWidth - paddingLeft - paddingRight;
    const actualHeight = mainbox.offsetHeight - paddingTop - paddingBottom;

    await this.chart.updateOptions({
      chart: {
        width: actualWidth,
        height: actualHeight,
      },
    });
  }
}