import { DateFormatter, Utils } from 'arm-common';
import p from 'prop-types';
import React, { useLayoutEffect, useMemo, useState } from 'react';

import { ChartContainer, useAm5, useAm5Colors, getRoot } from '../Am5.jsx';
import { AutoSize } from 'arm-core-layouts';


const classNamePrefix = 'armu_ai_chatbot-stacked-chart';

/**
 * Generates a stacked chart using the provided data and configuration.
 *
 * @param {Object} props - The configuration object for the chart.
 * @param {string} props.id - The unique identifier for the chart.
 * @param {string} props.xAxis - The field to use for the x-axis.
 * @param {string} props.yAxis - The field to use for the y-axis.
 * @param {Array} props.series - The series configuration for the chart.
 * @param {Array} props.data - The data to be displayed on the chart.
 * @return {ReactElement} The rendered stacked chart component.
 */
export default function StackedChart(props) {
    const { id, xAxis, series, isDateXAxis } = props;

    const [chartId] = useState(id || Utils.uuid(classNamePrefix));
    const am5 = useAm5();
    const am5Colors = useAm5Colors();
    const data = useMemo(() => {
        if (isDateXAxis) {
            return props.data.map((d) => ({...d, [xAxis]: DateFormatter.formatDate(d[xAxis], "DD/MM/YYYY") }))
        }
        return props.data;
    }, [props.data])

    useLayoutEffect(() => {
        if (am5 && data) {
            const root = getRoot(chartId);

            const chart = root.container.children.push(
                am5xy.XYChart.new(root, {
                    layout: root.verticalLayout
                })
            );

            const xRenderer = am5xy.AxisRendererX.new(root, {});

            const xAxisAm5 = chart.xAxes.push(
                am5xy.CategoryAxis.new(root, {
                    categoryField: xAxis,
                    renderer: xRenderer,
                    tooltip: am5.Tooltip.new(root, {})
                })
            );

            xRenderer.grid.template.setAll({
                location: 1
            })

            xAxisAm5.data.setAll(data);

            const yAxisAm5 = chart.yAxes.push(
                am5xy.ValueAxis.new(root, {
                    min: 0,
                    max: 100,
                    renderer: am5xy.AxisRendererY.new(root, {
                        strokeOpacity: 0.1
                    })
                })
            );

            chart.set("colors", am5.ColorSet.new(root, {
                colors: am5Colors
            }));

            if (series?.length) {
                const legend = chart.children.push(am5.Legend.new(root, {
                    centerX: am5.p50,
                    x: am5.p50,
                }));

                series.forEach(addSeries.bind({ root, chart, xAxisAm5, yAxisAm5, xAxis, data }));

                legend.data.setAll(chart.series.values);
            }
        }
    }, [am5, data]);

    return (
        <ChartContainer id={chartId} className={classNamePrefix} />
    );
}

StackedChart.defaultProps = {
    id: '',
    xAxis: '',
    series: [],
    data: null
}

StackedChart.propTypes = {
    id: p.string,
    xAxis: p.string.isRequired,
    series: p.arrayOf(p.shape({
        name: p.string,
        yAxis: p.string
    })).isRequired,
    data: p.arrayOf(p.object).isRequired
}

function addSeries(seriesConfig) {
    const { root, chart, xAxisAm5, yAxisAm5, xAxis, data } = this;

    const { name, yAxis } = seriesConfig;

    const series = chart.series.push(
        am5xy.ColumnSeries.new(root, {
            name,
            stacked: true,
            xAxis: xAxisAm5,
            yAxis: yAxisAm5,
            categoryXField: xAxis,
            valueYField: yAxis
        })
    );

    series.columns.template.setAll({
        tooltipText: "[bold]{name}[/]: {valueY}",
        tooltipY: am5.percent(10)
    });

    series.bullets.push(function () {
        return am5.Bullet.new(root, {
            sprite: am5.Label.new(root, {
                text: "{valueY}",
                fill: root.interfaceColors.get("alternativeText"),
                centerY: am5.p50,
                centerX: am5.p50,
                populateText: true
            })
        });
    });

    series.data.setAll(data);
    addRoundedCorners(series, chart, xAxisAm5);
    series.appear();
}

//TODO doesnt work
function addRoundedCorners(series, chart, xAxisAm5) {
    series.columns.template.adapters.add("cornerRadiusTL", function (radius, target) {
        return isTop.call({ chart, series, xAxisAm5 }, target.dataItem) ? 5 : 0;
    });
    series.columns.template.adapters.add("cornerRadiusTR", function (radius, target) {
        return isTop.call({ chart, series, xAxisAm5 }, target.dataItem) ? 5 : 0;
    });
}
function getCategoryDataItems(dataItem) {
    const index = this.xAxisAm5.categoryToIndex(dataItem.get("categoryX"));
    const items = [];
    this.chart.series.each((series) => {
        if (series.get("visible")) {
            const item = this.series.dataItems[index];
            if (item.get("valueY") >= 0) {
                items.push(item);
            }
            else {
                items.unshift(item);
            }
        }
    });
    return items;
}

function isTop(dataItem) {
    const items = getCategoryDataItems.call(this, dataItem);
    if (dataItem.get("valueY") >= 0) {
        return items.indexOf(dataItem) == (items.length - 1);
    }
    else {
        return items.indexOf(dataItem) == 0;
    }
}