(function nativeObservabilityRequestTimelineBehavior(
  Drupal,
  once,
  drupalSettings,
) {
  /**
   * Builds the series definitions for the timeline chart.
   *
   * @param {Object} series
   *   The timeline series keyed by metric name.
   *
   * @return {Array}
   *   The ECharts series definitions.
   */
  function buildSeriesDefinitions(series) {
    const definitions = [];

    if (Array.isArray(series.requests_per_second)) {
      definitions.push({
        key: "requests_per_second",
        name: Drupal.t("Requests/sec"),
        yAxisIndex: 0,
        areaStyle: {},
      });
    }

    if (Array.isArray(series.average_duration)) {
      definitions.push({
        key: "average_duration",
        name: Drupal.t("Avg Response Time"),
        yAxisIndex: 1,
      });
    }

    if (Array.isArray(series.p95_duration)) {
      definitions.push({
        key: "p95_duration",
        name: Drupal.t("P95 Latency"),
        yAxisIndex: 1,
      });
    }

    if (Array.isArray(series.error_rate)) {
      definitions.push({
        key: "error_rate",
        name: Drupal.t("Error Rate"),
        yAxisIndex: 2,
      });
    }

    return definitions;
  }

  /**
   * Builds the chart options for the activity timeline.
   *
   * @param {Object} settings
   *   The timeline settings delivered through drupalSettings.
   * @param {Array} definitions
   *   The resolved series definitions.
   *
   * @return {Object}
   *   The ECharts option object.
   */
  function buildChartOption(settings, definitions) {
    const firstSeries = settings.series[definitions[0].key] || [];
    const labels = firstSeries.map((item) => item.label ?? "");

    return {
      animation: true,
      tooltip: {
        trigger: "axis",
      },
      legend: {
        top: 0,
        left: "center",
        data: definitions.map((item) => item.name),
      },
      grid: {
        left: 56,
        right: 72,
        top: 56,
        bottom: 32,
      },
      xAxis: {
        type: "category",
        boundaryGap: false,
        data: labels,
      },
      yAxis: [
        {
          type: "value",
          name: Drupal.t("Req/s"),
          position: "left",
        },
        {
          type: "value",
          name: Drupal.t("Latency (ms)"),
          position: "right",
        },
        {
          type: "value",
          name: Drupal.t("Error %"),
          position: "right",
          offset: 64,
        },
      ],
      series: definitions.map((definition) => ({
        name: definition.name,
        type: "line",
        smooth: true,
        symbol: "none",
        yAxisIndex: definition.yAxisIndex,
        ...(definition.areaStyle
          ? {
              areaStyle: definition.areaStyle,
            }
          : {}),
        data: (settings.series[definition.key] || []).map((item) =>
          Number(item.value ?? 0),
        ),
      })),
    };
  }

  /**
   * Initializes a single timeline chart.
   *
   * @param {HTMLElement} element
   *   The chart host element.
   * @param {Object} settings
   *   The timeline settings for the host element.
   */
  function initTimelineChart(element, settings) {
    if (element.dataset.chartReady === "true") {
      return;
    }

    const echartsLib = window.echarts;

    if (!echartsLib) {
      element.innerHTML = `<div class="no-chart-fallback">${Drupal.t("Apache ECharts is not available.")}</div>`;
      return;
    }

    const definitions = buildSeriesDefinitions(settings.series);
    if (!definitions.length) {
      element.innerHTML = `<div class="no-chart-fallback">${Drupal.t("No chart series are available.")}</div>`;
      return;
    }

    if (!element.clientWidth || !element.clientHeight) {
      window.requestAnimationFrame(() => initTimelineChart(element, settings));
      return;
    }

    const chart = echartsLib.init(element);
    chart.setOption(buildChartOption(settings, definitions));
    chart.resize();
  }

  /**
   * Attaches request and AJAX activity timeline charts.
   */
  Drupal.behaviors.nativeObservabilityRequestTimeline = {
    attach(context) {
      const singleTimeline =
        drupalSettings.nativeObservabilityDashboard?.requestTimeline || null;
      const multipleTimelines =
        drupalSettings.nativeObservabilityDashboard?.timelines || {};
      let timelines = {};

      if (Object.keys(multipleTimelines).length) {
        timelines = multipleTimelines;
      } else if (singleTimeline) {
        timelines = { default: singleTimeline };
      }

      Object.values(timelines).forEach((settings) => {
        if (!settings || !settings.chart_id || !settings.series) {
          return;
        }

        once(
          `native-observability-timeline-${settings.chart_id}`,
          `[data-chart-id="${settings.chart_id}"]`,
          context,
        ).forEach((element) => {
          initTimelineChart(element, settings);
        });
      });
    },
  };
})(Drupal, once, drupalSettings);
