import {gql, useLazyQuery} from '@apollo/client';
import {Spinner, Stack, Text} from '@chakra-ui/react';
import {snakeCase} from 'change-case';
import React, {useEffect, useState} from 'react';
import {Bar, BarChart, CartesianGrid, Cell, Legend, Tooltip, XAxis, YAxis} from 'recharts';


export interface StackedBarComponentProps {
    componentName: string,
    title?: string,
    titleFontColor?: string,
    titleFontSize?: string,
    titleFontWeight?: string,
    table_name: string,
    data_columns: string[],
    orientation?: string,
    showLegend?: boolean,
    width: number,
    height: number,
    barsColor: string,
    barSize?: number,
}

const COLORS = [
    "#4ca2f9", "#028AE7", "#E6F3FD", "#F29B22", "#9685eb", "#f50422", "#c79ed2",
    "#0ec0ff", "#cb2582", "#63b598", "#ce7d78", "#51aed9", "#ea9e70", "#c9a941",
    "#a48a9e", "#648177", "#f205e6", "#1c0365", "#14a9ad", "#a4e43f", "#d298e2",
    "#6119d0", "#d2737d", "#c0a43c", "#f2510e", "#651be6", "#79806e", "#61da5e"
];

function StackedBarChartComponent(props: StackedBarComponentProps) {

    const {
        title,
        titleFontColor = "black",
        titleFontSize = "18px",
        titleFontWeight = "500",
        table_name = "",
        data_columns,
        orientation,
        showLegend = true,
        width,
        height,
        barsColor,
        barSize = 24
    } = props;

    const [barContent, setBarContent]: any[] = useState([]);

    useEffect(() => {
        if (data_columns.length >= 2) {
            fetchData()
        } else {
            console.log("Not enough data columns");
        }
    }, [data_columns]);

    let q = gql`
    query {
        ${snakeCase(table_name)} {
            ${data_columns.map(col => `${col}`).join(',')}
        }
    }`;

    const [fetchData, { loading, error }] = useLazyQuery(q, {
        onCompleted: (res) => {
            let mData = [...res[snakeCase(table_name)]];
            // sort array in descending order by value
            mData.sort((a, b) => (a.value < b.value) ? 1 : -1);
            setBarContent(mData);
        },
        onError: (error) => {
            console.log(error);
        }
    });

    function isVertical() {
        return orientation === "vertical";
    }

    return (
        <Stack alignItems={"center"} py={8} px={3} w="fit-content" h="fit-content"
            border="1px solid #F2F2F2" borderRadius={"8px"} bg="white">
            <Text fontSize={titleFontSize} fontWeight={titleFontWeight}
                color={titleFontColor}>{title}</Text>
            {loading ? <Spinner m={12} />
                : error ? <Text color="red.400">{error.message}</Text>
                    : data_columns.length < 2 ?
                        <Text color="red.400">
                            Not enough data columns (required: 2)
                        </Text>
                        :
                        isVertical() ?
                            <BarChart
                                layout={isVertical() ? "vertical" : "horizontal"}
                                width={width}
                                height={height}
                                data={barContent}
                                margin={{
                                    top: 5,
                                    right: 30,
                                    left: 20,
                                    bottom: 5,
                                }}
                            >
                                <CartesianGrid strokeDasharray="3 3" />
                                <XAxis type="number" />
                                <YAxis type="category"
                                    axisLine={false}
                                    tickLine={false}
                                    dataKey={"name"} />
                                <Tooltip />
                                {showLegend && <Legend />}
                                {data_columns.map((col: string, i: number) => {
                                    if (col !== "name") { //Highly experimental piece of code.
                                        return (
                                            <Bar minPointSize={2}
                                                stackId="a"
                                                barSize={barSize} key={i} dataKey={col} fill={COLORS[i]}>
                                                {barContent.map((d: any, idx: number) => {
                                                    return <Cell key={d[`${col}`]} />;
                                                })}
                                            </Bar>
                                        );
                                    }
                                })}

                            </BarChart>

                            :

                            <BarChart
                                layout={"horizontal"}
                                width={width}
                                height={height}
                                data={barContent}
                                margin={{
                                    top: 5,
                                    right: 30,
                                    left: 20,
                                    bottom: 5,
                                }}
                            >
                                <CartesianGrid strokeDasharray="3 3" />
                                <XAxis dataKey={"name"} />
                                <YAxis />
                                <Tooltip />
                                {showLegend && <Legend />}
                                {data_columns.map((col: string, i: number) => {
                                    if (col !== "name") { //Highly experimental piece of code.
                                        return (
                                            <Bar minPointSize={2}
                                                stackId="a"
                                                barSize={barSize} key={i} dataKey={col} fill={COLORS[i]}>
                                                {barContent.map((d: any, idx: number) => {
                                                    return <Cell key={d[`${col}`]} />;
                                                })}
                                            </Bar>
                                        );
                                    }
                                })}
                            </BarChart>
            }

        </Stack>
    );
}

export default StackedBarChartComponent;