<script lang="ts">
  import { analystEstimateComponent, stockTicker } from "$lib/store";
  import { abbreviateNumber, computeGrowthSingleList } from "$lib/utils";
  import EstimationGraph from "$lib/components/EstimationGraph.svelte";
  import Lazy from "svelte-lazy";
  import { mode } from "mode-watcher";

  export let data;

  let analystEstimateList = [];
  let isLoaded = false;

  let xData = [];
  let optionsRevenue = null;
  let optionsEPS = null;
  let optionsNetIncome = null;
  let optionsEbitda = null;

  let optionsRevenueGrowth = null;
  let optionsEPSGrowth = null;
  let optionsNetIncomeGrowth = null;
  let optionsEbitdaGrowth = null;

  let revenueDateList = [];
  let avgRevenueList = [];
  let lowRevenueList = [];
  let highRevenueList = [];

  let epsDateList = [];
  let avgEPSList = [];
  let lowEPSList = [];
  let highEPSList = [];

  let netIncomeDateList = [];
  let avgNetIncomeList = [];
  let lowNetIncomeList = [];
  let highNetIncomeList = [];

  let ebitdaDateList = [];
  let avgEbitdaList = [];
  let lowEbitdaList = [];
  let highEbitdaList = [];

  let revenueAvgGrowthList = [];
  let epsAvgGrowthList = [];
  let netIncomeAvgGrowthList = [];
  let ebitdaAvgGrowthList = [];

  function fillMissingDates(dates, highGrowthList) {
    // Get the current year
    const currentYear = new Date().getFullYear();
    const currentFiscalYear = `FY${currentYear % 100}`; // Get the current fiscal year (e.g., 2024 => FY24)

    // Create a map from the highGrowthList for quick lookup
    const highGrowthMap = new Map(
      highGrowthList?.map((item) => [`FY${item.FY}`, item]),
    );

    // Generate the complete list based on the dates array
    return dates?.map((date) => {
      // Check if the date is the current fiscal year or it exists in the map
      const data = highGrowthMap?.get(date) || {
        FY: date?.slice(2),
        val: null,
        growth: null,
      };

      // If the fiscal year is the current one, set val and growth to null
      if (date === currentFiscalYear) {
        data.val = null;
        data.growth = null;
      }

      return data;
    });
  }

  function computeGrowthList(tableActualRevenue, tableForecastRevenue) {
    return tableActualRevenue?.map((item, index) => {
      const currentFY = item?.FY;

      // If it's the first item or the list is empty, return null growth
      if (index === 0 || tableActualRevenue.length === 0) {
        return { FY: currentFY, growth: null };
      }

      // If actual value is null, compute growth based on forecast values
      if (item?.val === null) {
        const prevForecastVal = tableForecastRevenue[index - 1]?.val ?? 0;
        const currentForecastVal = tableForecastRevenue[index]?.val ?? 0;

        if (prevForecastVal === 0 || currentForecastVal === 0) {
          return { FY: currentFY, growth: null };
        }

        const forecastGrowth =
          ((currentForecastVal - prevForecastVal) / Math.abs(prevForecastVal)) *
          100;

        return {
          FY: currentFY,
          growth:
            forecastGrowth !== 0 ? Number(forecastGrowth?.toFixed(2)) : null,
        };
      }

      // Compute actual growth for non-null actual values
      const prevActualVal = tableActualRevenue[index - 1]?.val ?? 0;
      const currentActualVal = item?.val ?? 0;

      if (prevActualVal === 0 || currentActualVal === 0) {
        return { FY: currentFY, growth: null };
      }

      const actualGrowth =
        ((currentActualVal - prevActualVal) / Math.abs(prevActualVal)) * 100;

      return {
        FY: currentFY,
        growth: actualGrowth !== 0 ? Number(actualGrowth.toFixed(2)) : null,
      };
    });
  }

  function findIndex(data) {
    const currentYear = new Date().getFullYear();
    // Find the index where the item's date is greater than or equal to the current year and revenue is null
    let index = data.findIndex(
      (item) => item.date >= currentYear && item?.revenue === null,
    );

    // Check if there is any item for the current year with non-null revenue
    const hasNonNullRevenue = data?.some(
      (item) => item.date === currentYear && item.revenue !== null,
    );

    // Add +1 to the index if the condition is met
    return index !== -1 && hasNonNullRevenue ? index + 1 : index;
  }

  let tableActualRevenue = [];
  let tableForecastRevenue = [];
  let tableCombinedRevenue = [];

  let tableActualEPS = [];
  let tableForecastEPS = [];
  let tableCombinedEPS = [];

  let tableActualNetIncome = [];
  let tableCombinedNetIncome = [];
  let tableForecastNetIncome = [];

  let tableActualEbitda = [];
  let tableCombinedEbitda = [];
  let tableForecastEbitda = [];

  function getPlotOptions(dataType: string) {
    let dates = [];
    let valueList = [];
    let avgList = [];
    let lowList = [];
    let highList = [];
    let filteredData =
      analystEstimateList?.filter((item) => item.date >= 2019) ?? [];
    const stopIndex = findIndex(filteredData);

    if (filteredData) {
      filteredData.forEach((item, index) => {
        const date = item.date?.toString().slice(-2);
        const isAfterStartIndex = stopIndex <= index + 1;
        dates.push(`FY${date}`);
        switch (dataType) {
          case "Revenue":
            valueList.push(isAfterStartIndex ? null : item.revenue);
            avgList.push(isAfterStartIndex ? item?.estimatedRevenueAvg : null);
            lowList.push(isAfterStartIndex ? item?.estimatedRevenueLow : null);
            highList.push(
              isAfterStartIndex ? item?.estimatedRevenueHigh : null,
            );
            break;
          case "EPS":
            valueList.push(isAfterStartIndex ? null : item.eps);
            avgList.push(isAfterStartIndex ? item.estimatedEpsAvg : null);
            lowList.push(isAfterStartIndex ? item.estimatedEpsLow : null);
            highList.push(isAfterStartIndex ? item.estimatedEpsHigh : null);
            break;
          case "NetIncome":
            valueList.push(isAfterStartIndex ? null : item.netIncome);
            avgList.push(isAfterStartIndex ? item.estimatedNetIncomeAvg : null);
            lowList.push(isAfterStartIndex ? item.estimatedNetIncomeLow : null);
            highList.push(
              isAfterStartIndex ? item.estimatedNetIncomeHigh : null,
            );
            break;
          case "Ebitda":
            valueList.push(isAfterStartIndex ? null : item.ebitda);
            avgList.push(isAfterStartIndex ? item.estimatedEbitdaAvg : null);
            lowList.push(isAfterStartIndex ? item.estimatedEbitdaLow : null);
            highList.push(isAfterStartIndex ? item.estimatedEbitdaHigh : null);
            break;
          default:
            break;
        }
      });
    }

    try {
      const lastValue = valueList[stopIndex - 2];
      avgList[stopIndex - 2] = lastValue;
      lowList[stopIndex - 2] = lastValue;
      highList[stopIndex - 2] = lastValue;
    } catch (e) {
      console.log(e);
    }

    // Normalize the data if needed (not required in this case, but leaving it here for reference)

    let currentYearSuffix = new Date().getFullYear()?.toString().slice(-2);
    let searchString = `FY${currentYearSuffix}`;
    let currentYearIndex = dates?.findIndex((date) => date === searchString);

    // Assign to global variables based on dataType
    if (dataType === "Revenue") {
      revenueDateList = dates?.slice(currentYearIndex) || [];
      avgRevenueList =
        avgList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: revenueDateList[index]?.slice(2),
          val: val,
        })) || [];
      lowRevenueList =
        lowList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: revenueDateList[index]?.slice(2),
          val: val,
        })) || [];
      highRevenueList =
        highList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: revenueDateList[index]?.slice(2),
          val: val,
        })) || [];
    } else if (dataType === "EPS") {
      epsDateList = dates?.slice(currentYearIndex) || [];
      avgEPSList =
        avgList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: epsDateList[index]?.slice(2),
          val: val,
        })) || [];
      lowEPSList =
        lowList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: epsDateList[index]?.slice(2),
          val: val,
        })) || [];
      highEPSList =
        highList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: epsDateList[index]?.slice(2),
          val: val,
        })) || [];
    } else if (dataType === "NetIncome") {
      netIncomeDateList = dates?.slice(currentYearIndex) || [];
      avgNetIncomeList =
        avgList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: netIncomeDateList[index]?.slice(2),
          val: val,
        })) || [];
      lowNetIncomeList =
        lowList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: netIncomeDateList[index]?.slice(2),
          val: val,
        })) || [];
      highNetIncomeList =
        highList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: netIncomeDateList[index]?.slice(2),
          val: val,
        })) || [];
    } else if (dataType === "Ebitda") {
      ebitdaDateList = dates?.slice(currentYearIndex) || [];
      avgEbitdaList =
        avgList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: ebitdaDateList[index]?.slice(2),
          val: val,
        })) || [];
      lowEbitdaList =
        lowList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: ebitdaDateList[index]?.slice(2),
          val: val,
        })) || [];
      highEbitdaList =
        highList?.slice(currentYearIndex)?.map((val, index) => ({
          FY: ebitdaDateList[index]?.slice(2),
          val: val,
        })) || [];
    }
    const growthList = dates?.map((date) => {
      const fy = parseInt(date.replace("FY", ""), 10); // Extract numeric FY value
      const listToUse =
        dataType === "Revenue"
          ? revenueAvgGrowthList
          : dataType === "EPS"
            ? epsAvgGrowthList
            : dataType === "NetIncome"
              ? netIncomeAvgGrowthList
              : ebitdaAvgGrowthList; // Select the correct growth list
      const growth = listToUse?.find((r) => r.FY === fy); // Find matching FY
      return growth ? growth?.growth : null; // Return growth or null if not found
    });

    const option = {
      credits: {
        enabled: false,
      },
      legend: {
        enabled: false,
      },
      plotOptions: {
        series: {
          animation: false,
          marker: {
            enabled: false,
            states: {
              hover: { enabled: false }, // Disable marker on hover
              select: { enabled: false }, // Disable marker on selection
            },
          },
        },
      },
      chart: {
        type: "line",
        backgroundColor: $mode === "light" ? "#fff" : "#09090B",
        plotBackgroundColor: $mode === "light" ? "#fff" : "#09090B",
        height: 360,
        animation: false,
      },
      title: {
        text: null,
      },
      tooltip: {
        shared: true,
        useHTML: true,
        backgroundColor: "rgba(0, 0, 0, 0.8)", // Semi-transparent black
        borderColor: "rgba(255, 255, 255, 0.2)", // Slightly visible white border
        borderWidth: 1,
        style: {
          color: "#fff",
          fontSize: "16px",
          padding: "10px",
        },
        borderRadius: 4,
        formatter: function () {
          // Format the x value to display time in hh:mm format
          let tooltipContent = `<span class=" m-auto  text-[1rem] font-[501]">${
            this?.x
          }</span><br>`;

          // Loop through each point in the shared tooltip
          this.points?.forEach((point) => {
            tooltipContent += `<span class=" font-semibold text-sm">${point.series.name}:</span> 
          <span class=" font-normal text-sm" >${abbreviateNumber(
            point.y,
          )}</span><br>`;
          });

          return tooltipContent;
        },
      },
      xAxis: {
        categories: dates,
        type: "datetime",
        endOnTick: false,
        categories: dates,
        crosshair: {
          color: $mode === "light" ? "black" : "white", // Set the color of the crosshair line
          width: 1, // Adjust the line width as needed
          dashStyle: "Solid",
        },

        labels: {
          style: {
            color: $mode === "light" ? "black" : "white",
            fontSize: "12px",
          },
        },
      },
      yAxis: {
        gridLineWidth: 1,
        gridLineColor: $mode === "light" ? "#d1d5dc" : "#111827",
        labels: {
          style: { color: $mode === "light" ? "black" : "white" },
        },
        title: { text: null },
        opposite: true,
      },
      series: [
        {
          name: "Actual",
          data: valueList,
          color: $mode === "light" ? "#2C6288" : "white",
          animation: false,
        },
        {
          name: "Avg",
          data: avgList,
          color: $mode === "light" ? "#2C6288" : "white",
          dashStyle: "Dash", // Dashed line style
          animation: false,
          marker: {
            enabled: false,
          },
        },
        {
          name: "Low",
          data: lowList,
          // If you want a dashed line with a different color, set the series color to that color.
          color: $mode === "light" ? "#8AAAC0" : "#c2c7cf",
          dashStyle: "Dash",
          animation: false,
        },
        {
          name: "High",
          data: highList,
          color: $mode === "light" ? "#8AAAC0" : "#c2c7cf",
          dashStyle: "Dash",
          animation: false,
        },
      ],
    };

    let highGrowthList = [];
    let lowGrowthList = [];
    if (dataType === "Revenue") {
      highGrowthList = computeGrowthSingleList(highRevenueList, avgRevenueList);
      lowGrowthList = computeGrowthSingleList(lowRevenueList, avgRevenueList);
    } else if (dataType === "EPS") {
      highGrowthList = computeGrowthSingleList(highEPSList, avgEPSList);
      lowGrowthList = computeGrowthSingleList(lowEPSList, avgEPSList);
    } else if (dataType === "NetIncome") {
      highGrowthList = computeGrowthSingleList(
        highNetIncomeList,
        avgNetIncomeList,
      );
      lowGrowthList = computeGrowthSingleList(
        lowNetIncomeList,
        avgNetIncomeList,
      );
    } else if (dataType === "Ebitda") {
      highGrowthList = computeGrowthSingleList(highEbitdaList, avgEbitdaList);
      lowGrowthList = computeGrowthSingleList(lowEbitdaList, avgEbitdaList);
    }

    highGrowthList = fillMissingDates(dates, highGrowthList)?.map(
      (item) => item?.growth,
    );

    lowGrowthList = fillMissingDates(dates, lowGrowthList)?.map(
      (item) => item?.growth,
    );

    const optionsGrowth = {
      credits: {
        enabled: false,
      },
      legend: {
        enabled: false,
      },
      plotOptions: {
        series: {
          animation: false,
        },
      },
      chart: {
        type: "column",
        backgroundColor: $mode === "light" ? "#fff" : "#09090B",
        plotBackgroundColor: $mode === "light" ? "#fff" : "#09090B",
        height: 360,
        animation: false,
      },
      title: {
        text: null,
      },
      tooltip: {
        shared: true,
        useHTML: true,
        backgroundColor: "rgba(0, 0, 0, 0.8)", // Semi-transparent black
        borderColor: "rgba(255, 255, 255, 0.2)", // Slightly visible white border
        borderWidth: 1,
        style: {
          color: "white",
          fontSize: "14px",
          padding: "10px",
        },
        borderRadius: 4,
        formatter: function () {
          // Find the main series point (exclude error bar points)
          const mainPoint = this.points.find(
            (p) => p.series.type !== "errorbar",
          );
          const idx = mainPoint.point.index;
          const mainValue = mainPoint.y;
          let tooltipContent = `<b style="font-weight:501;">${dates[idx]}</b><br>`;

          // Use highGrowthList and lowGrowthList from outer scope
          const high = highGrowthList[idx];
          const low = lowGrowthList[idx];

          if (high && high !== "N/A") {
            tooltipContent += `<span style="font-weight:501;">High:</span> ${high.toFixed(2)}<br>`;
          }
          if (mainValue && mainValue !== "N/A") {
            tooltipContent += `<span style="font-weight:501;">Avg:</span> ${mainValue.toFixed(2)}<br>`;
          }
          if (low && low !== "N/A") {
            tooltipContent += `<span style="font-weight:501;">Low:</span> ${low.toFixed(2)}<br>`;
          }
          return tooltipContent;
        },
      },

      xAxis: {
        categories: dates,
        type: "datetime",
        labels: {
          style: {
            color: $mode === "light" ? "black" : "white",
            fontSize: "12px",
          },
        },
      },
      yAxis: {
        gridLineWidth: 1,
        gridLineColor: $mode === "light" ? "#d1d5dc" : "#111827",
        labels: {
          style: { color: $mode === "light" ? "black" : "white" },
        },
        title: { text: null },
        opposite: true,
      },
      series: [
        {
          // Dynamically set the series name based on dataType
          name:
            dataType === "Revenue"
              ? "Revenue Growth"
              : dataType === "EPS"
                ? "EPS Growth"
                : dataType === "NetIncome"
                  ? "Net Income Growth"
                  : "EBITDA Growth",
          data: growthList?.map((value) => ({
            y: value,
            // Set color based on the sign of the value
            color:
              value >= 0
                ? $mode === "light"
                  ? "#338D73"
                  : "#00FC50"
                : "#ED3333",
            borderColor:
              value >= 0
                ? $mode === "light"
                  ? "#338D73"
                  : "#00FC50"
                : "#ED3333",
            borderRadius: "1px",
          })),
          zIndex: 5,
          // 'smooth' is not applicable for column charts
        },
        {
          name: "Error Bars",
          type: "errorbar",
          // Prepare data as [low, high] pairs for each index.
          data: growthList?.map((value, index) => {
            const high = highGrowthList[index];
            const low = lowGrowthList[index];
            // If either high or low is null/undefined, return nulls.
            return high != null && low != null ? [low, high] : [null, null];
          }),
          color: $mode === "light" ? "black" : "white",
          lineWidth: 1, // Thicker lines for error bars
          whiskerLength: 10, // Adjust whisker length as needed
          zIndex: 10,
          // Disable tooltip for error bar points
          tooltip: {
            pointFormatter: function () {
              return "";
            },
          },
        },
      ],
    };

    if (dataType === "Revenue") {
      optionsRevenue = option;
      optionsRevenueGrowth = optionsGrowth;
    } else if (dataType === "EPS") {
      optionsEPS = option;
      optionsEPSGrowth = optionsGrowth;
    } else if (dataType === "NetIncome") {
      optionsNetIncome = option;
      optionsNetIncomeGrowth = optionsGrowth;
    } else if (dataType === "Ebitda") {
      optionsEbitda = option;
      optionsEbitdaGrowth = optionsGrowth;
    }
  }

  //To-do: Optimize this piece of shit
  function prepareData() {
    tableActualRevenue = [];
    tableForecastRevenue = [];
    tableCombinedRevenue = [];

    tableActualEPS = [];
    tableCombinedEPS = [];
    tableForecastEPS = [];

    tableActualNetIncome = [];
    tableCombinedNetIncome = [];
    tableForecastNetIncome = [];

    tableActualEbitda = [];
    tableCombinedEbitda = [];
    tableForecastEbitda = [];

    revenueAvgGrowthList = [];
    epsAvgGrowthList = [];
    netIncomeAvgGrowthList = [];
    ebitdaAvgGrowthList = [];

    let filteredData =
      analystEstimateList?.filter((item) => item.date >= 2015) ?? [];

    xData = filteredData?.map(({ date }) => Number(String(date)?.slice(-2)));
    //============================//
    //Revenue Data
    filteredData?.forEach((item) => {
      tableActualRevenue?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.revenue,
      });
      tableForecastRevenue?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.estimatedRevenueAvg,
        numOfAnalysts: item?.numOfAnalysts,
      });
    });

    tableCombinedRevenue = tableActualRevenue?.map((item1) => {
      // Find the corresponding item in data2 based on "FY"
      const item2 = tableForecastRevenue?.find(
        (item2) => item2?.FY === item1?.FY,
      );

      // If the value in data1 is null, replace it with the value from data2
      return {
        FY: item1.FY,
        val: item1.val === null ? item2.val : item1.val,
        numOfAnalysts: item2.numOfAnalysts,
      };
    });

    //============================//
    //NetIncome Data
    filteredData?.forEach((item) => {
      tableActualNetIncome?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.netIncome,
      });
      tableForecastNetIncome?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.estimatedNetIncomeAvg,
      });
    });

    tableCombinedNetIncome = tableActualNetIncome?.map((item1) => {
      // Find the corresponding item in data2 based on "FY"
      const item2 = tableForecastNetIncome?.find(
        (item2) => item2?.FY === item1?.FY,
      );

      // If the value in data1 is null, replace it with the value from data2
      return {
        FY: item1.FY,
        val: item1.val === null ? item2.val : item1.val,
      };
    });

    //============================//
    //Ebitda Data
    filteredData?.forEach((item) => {
      tableActualEbitda?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.ebitda,
      });
      tableForecastEbitda?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.estimatedEbitdaAvg,
      });
    });

    tableCombinedEbitda = tableActualEbitda?.map((item1) => {
      // Find the corresponding item in data2 based on "FY"
      const item2 = tableForecastEbitda?.find(
        (item2) => item2?.FY === item1?.FY,
      );

      // If the value in data1 is null, replace it with the value from data2
      return {
        FY: item1.FY,
        val: item1.val === null ? item2.val : item1.val,
      };
    });

    //============================//
    //EPS Data
    filteredData?.forEach((item) => {
      tableActualEPS?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.eps,
      });
      tableForecastEPS?.push({
        FY: Number(String(item?.date)?.slice(-2)),
        val: item?.estimatedEpsAvg,
      });
    });

    tableCombinedEPS = tableActualEPS?.map((item1) => {
      // Find the corresponding item in data2 based on "FY"
      const item2 = tableForecastEPS?.find((item2) => item2?.FY === item1?.FY);

      // If the value in data1 is null, replace it with the value from data2
      return {
        FY: item1.FY,
        val: item1.val === null ? item2.val : item1.val,
      };
    });

    //Values coincide with table values for crosscheck
    revenueAvgGrowthList = computeGrowthList(
      tableActualRevenue,
      tableCombinedRevenue,
    );
    netIncomeAvgGrowthList = computeGrowthList(
      tableActualNetIncome,
      tableCombinedNetIncome,
    );

    ebitdaAvgGrowthList = computeGrowthList(
      tableActualEbitda,
      tableCombinedEbitda,
    );
    epsAvgGrowthList = computeGrowthList(tableActualEPS, tableCombinedEPS);
  }

  $: {
    if ($stockTicker || $mode) {
      isLoaded = false;
      analystEstimateList = [];
      analystEstimateList = data?.getAnalystEstimate || [];
      if (analystEstimateList?.length !== 0) {
        prepareData();
        $analystEstimateComponent = true;
        getPlotOptions("Revenue");
        getPlotOptions("EPS");
        getPlotOptions("NetIncome");
        getPlotOptions("Ebitda");
      } else {
        $analystEstimateComponent = false;
      }
      isLoaded = true;
    }
  }
</script>

<section class="overflow-hidden h-full pb-8 sm:pb-2">
  <main class="overflow-hidden">
    <div class="w-full m-auto">
      <div class="flex flex-row items-center"></div>

      {#if isLoaded}
        {#if analystEstimateList?.length !== 0}
          <div
            class="no-scrollbar flex justify-start items-center w-screen sm:w-full mt-2 m-auto overflow-x-auto pr-5 sm:pr-0"
          >
            <table
              class="table table-sm table-compact no-scrollbar rounded-none sm:rounded-md w-full bg-white dark:bg-table border border-gray-300 dark:border-gray-800 m-auto"
            >
              <thead class="text-muted dark:text-white dark:bg-default">
                <tr class="">
                  <th class=" font-semibold text-sm text-start">Fiscal Year</th>
                  {#each xData as item}
                    <td class="z-20 font-semibold text-sm text-end"
                      >{"FY" + item}</td
                    >
                  {/each}
                </tr>
              </thead>
              <tbody>
                <tr class=" ">
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] text-start font-normal"
                  >
                    Revenue
                  </th>
                  {#each tableCombinedRevenue as item}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {item?.val === "0.00" ||
                      item?.val === null ||
                      item?.val === 0
                        ? "n/a"
                        : abbreviateNumber(item?.val.toFixed(2))}
                    </td>
                  {/each}
                </tr>

                <tr class="bg-[#F6F7F8] dark:bg-odd">
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] text-start font-normal"
                  >
                    Revenue Growth
                  </th>
                  {#each computeGrowthList(tableActualRevenue, tableCombinedRevenue) as item, index}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {#if index === 0 || item?.growth === null}
                        n/a
                      {:else if tableActualRevenue[index]?.val === null}
                        <span
                          class="text-orange-600 dark:text-orange-400 {item?.growth >
                          0
                            ? "before:content-['+']"
                            : ''}"
                        >
                          {item?.growth}%&#42;
                        </span>
                      {:else}
                        <span
                          class={item?.growth > 0
                            ? "text-green-600 dark:text-[#00FC50] before:content-['+']"
                            : item?.growth < 0
                              ? "text-red-600 dark:text-[#FF2F1F]"
                              : ""}
                        >
                          {item?.growth}%
                        </span>
                      {/if}
                    </td>
                  {/each}
                </tr>

                <tr class="">
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] text-start font-normal"
                  >
                    EPS
                  </th>
                  {#each tableCombinedEPS as item}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {item?.val === "0.00" ||
                      item?.val === null ||
                      item?.val === 0
                        ? "-"
                        : abbreviateNumber(item?.val.toFixed(2))}
                    </td>
                  {/each}
                </tr>

                <tr class="bg-[#F6F7F8] dark:bg-odd">
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] font-normal text-start"
                  >
                    EPS Growth
                  </th>
                  {#each computeGrowthList(tableActualEPS, tableCombinedEPS) as item, index}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {#if index === 0 || item?.growth === null}
                        n/a
                      {:else if tableActualRevenue[index]?.val === null}
                        <span
                          class="text-orange-600 dark:text-orange-400 {item?.growth >
                          0
                            ? "before:content-['+']"
                            : ''}"
                        >
                          {item?.growth}%&#42;
                        </span>
                      {:else}
                        <span
                          class={item?.growth > 0
                            ? "text-green-600 dark:text-[#00FC50] before:content-['+']"
                            : item?.growth < 0
                              ? "text-red-600 dark:text-[#FF2F1F]"
                              : ""}
                        >
                          {item?.growth}%
                        </span>
                      {/if}
                    </td>
                  {/each}
                </tr>
                <tr>
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] text-start font-normal"
                  >
                    Net Income
                  </th>
                  {#each tableCombinedNetIncome as item}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {item?.val === "0.00" ||
                      item?.val === null ||
                      item?.val === 0
                        ? "n/a"
                        : abbreviateNumber(item?.val.toFixed(2))}
                    </td>
                  {/each}
                </tr>

                <tr class="bg-[#F6F7F8] dark:bg-odd">
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] font-normal text-start"
                  >
                    Net Income Growth
                  </th>
                  {#each computeGrowthList(tableActualNetIncome, tableCombinedNetIncome) as item, index}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {#if index === 0 || item?.growth === null}
                        n/a
                      {:else if tableActualNetIncome[index]?.val === null}
                        <span
                          class="text-orange-600 dark:text-orange-400 {item?.growth >
                          0
                            ? "before:content-['+']"
                            : ''}"
                        >
                          {item?.growth}%&#42;
                        </span>
                      {:else}
                        <span
                          class={item?.growth > 0
                            ? "text-green-600 dark:text-[#00FC50] before:content-['+']"
                            : item?.growth < 0
                              ? "text-red-600 dark:text-[#FF2F1F]"
                              : ""}
                        >
                          {item?.growth}%
                        </span>
                      {/if}
                    </td>
                  {/each}
                </tr>

                <tr>
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] text-start font-normal"
                  >
                    EBITDA
                  </th>
                  {#each tableCombinedEbitda as item}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {item?.val === "0.00" ||
                      item?.val === null ||
                      item?.val === 0
                        ? "n/a"
                        : abbreviateNumber(item?.val.toFixed(2))}
                    </td>
                  {/each}
                </tr>

                <tr class="bg-[#F6F7F8] dark:bg-odd">
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] font-normal text-start"
                  >
                    EBITDA Growth
                  </th>
                  {#each computeGrowthList(tableActualEbitda, tableCombinedEbitda) as item, index}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {#if index === 0 || item?.growth === null}
                        n/a
                      {:else if tableActualEbitda[index]?.val === null}
                        <span
                          class="text-orange-600 dark:text-orange-400 {item?.growth >
                          0
                            ? "before:content-['+']"
                            : ''}"
                        >
                          {item?.growth}%&#42;
                        </span>
                      {:else}
                        <span
                          class={item?.growth > 0
                            ? "text-green-600 dark:text-[#00FC50] before:content-['+']"
                            : item?.growth < 0
                              ? "text-red-600 dark:text-[#FF2F1F]"
                              : ""}
                        >
                          {item?.growth}%
                        </span>
                      {/if}
                    </td>
                  {/each}
                </tr>

                <tr>
                  <th
                    class=" whitespace-nowrap text-sm sm:text-[1rem] text-start font-normal"
                    >No. Analysts</th
                  >
                  {#each tableCombinedRevenue as item}
                    <td class=" text-sm sm:text-[1rem] text-end">
                      {#if item?.FY > 24}
                        {item?.numOfAnalysts === (null || 0)
                          ? "n/a"
                          : item?.numOfAnalysts}
                      {:else}
                        -
                      {/if}
                    </td>
                  {/each}
                </tr>
              </tbody>
            </table>
          </div>
          <div class=" text-sm mt-2">
            Historical EPS numbers are GAAP, while forecasted numbers may be
            non-GAAP.
          </div>
          <div class="text-orange-600 dark:text-orange-400 text-sm mt-2">
            &#42; This value depends on the forecast
          </div>
          <!--
            <div class="mt-5 text-gray-100 text-sm sm:text-[1rem] sm:rounded-md h-auto border border-gray-600 p-4">
              <svg class="w-5 h-5 inline-block mr-0.5 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"
                ><path fill="#fff" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16" /></svg
              >
              For the current Fiscal Year we use available quarterly data. Complete annual data, used to compare against analyst estimates, is only finalized after the year ends.
            </div>
            -->
        {/if}
      {:else}
        <div class="flex justify-center items-center h-80">
          <div class="relative">
            <label
              class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
            >
              <span class="loading loading-spinner loading-md text-gray-400"
              ></span>
            </label>
          </div>
        </div>
      {/if}

      <div class="space-y-6 lg:grid lg:grid-cols-2 lg:gap-6 lg:space-y-0 mt-10">
        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="Revenue"
            config={optionsRevenue}
            tableDataList={revenueDateList}
            highDataList={highRevenueList}
            avgDataList={avgRevenueList}
            lowDataList={lowRevenueList}
          />
        </Lazy>

        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="Revenue Growth"
            config={optionsRevenueGrowth}
            tableDataList={revenueDateList}
            highDataList={highRevenueList}
            avgDataList={avgRevenueList}
            lowDataList={lowRevenueList}
            avgGrowthList={revenueAvgGrowthList}
            graphType="growth"
          />
        </Lazy>

        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="EPS"
            config={optionsEPS}
            tableDataList={epsDateList}
            highDataList={highEPSList}
            avgDataList={avgEPSList}
            lowDataList={lowEPSList}
          />
        </Lazy>

        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="EPS Growth"
            config={optionsEPSGrowth}
            tableDataList={epsDateList}
            highDataList={highEPSList}
            avgDataList={avgEPSList}
            lowDataList={lowEPSList}
            avgGrowthList={epsAvgGrowthList}
            graphType="growth"
          />
        </Lazy>

        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="Net Income"
            config={optionsNetIncome}
            tableDataList={netIncomeDateList}
            highDataList={highNetIncomeList}
            avgDataList={avgNetIncomeList}
            lowDataList={lowNetIncomeList}
          />
        </Lazy>

        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="Net Income Growth"
            config={optionsNetIncomeGrowth}
            tableDataList={netIncomeDateList}
            highDataList={highNetIncomeList}
            avgDataList={avgNetIncomeList}
            lowDataList={lowNetIncomeList}
            avgGrowthList={netIncomeAvgGrowthList}
            graphType="growth"
          />
        </Lazy>

        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="EBITDA"
            config={optionsEbitda}
            tableDataList={ebitdaDateList}
            highDataList={highEbitdaList}
            avgDataList={avgEbitdaList}
            lowDataList={lowEbitdaList}
          />
        </Lazy>

        <Lazy fadeOption={{ delay: 100, duration: 100 }} keep={true}>
          <EstimationGraph
            userTier={data?.user?.tier}
            title="EBITDA Growth"
            config={optionsEbitdaGrowth}
            tableDataList={ebitdaDateList}
            highDataList={highEbitdaList}
            avgDataList={avgEbitdaList}
            lowDataList={lowEbitdaList}
            avgGrowthList={ebitdaAvgGrowthList}
            graphType="growth"
          />
        </Lazy>
      </div>
    </div>
  </main>
</section>

<style>
  .app {
    height: 300px;
    max-width: 100%; /* Ensure chart width doesn't exceed the container */
  }

  @media (max-width: 640px) {
    .app {
      height: 210px;
    }
  }

  .chart {
    width: 100%;
  }
</style>
