import { Button, Typography } from 'antd';
import getQueryResult from 'api/widgets/getQuery';
import { GraphOnClickHandler } from 'components/Graph';
import Spinner from 'components/Spinner';
import TimePreference from 'components/TimePreferenceDropDown';
import GridGraphComponent from 'container/GridGraphComponent';
import {
	timeItems,
	timePreferance,
	timePreferenceType,
} from 'container/NewWidget/RightContainer/timeItems';
import convertToNanoSecondsToSecond from 'lib/convertToNanoSecondsToSecond';
import getChartData from 'lib/getChartData';
import GetMaxMinTime from 'lib/getMaxMinTime';
import GetMinMax from 'lib/getMinMax';
import getStartAndEndTime from 'lib/getStartAndEndTime';
import getStep from 'lib/getStep';
import React, { useCallback, useState } from 'react';
import { useQueries } from 'react-query';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { PromQLWidgets } from 'types/api/dashboard/getAll';
import { GlobalReducer } from 'types/reducer/globalTime';

import { NotFoundContainer, TimeContainer } from './styles';

function FullView({
	widget,
	fullViewOptions = true,
	onClickHandler,
	name,
	yAxisUnit,
}: FullViewProps): JSX.Element {
	const { minTime, maxTime, selectedTime: globalSelectedTime } = useSelector<
		AppState,
		GlobalReducer
	>((state) => state.globalTime);

	const getSelectedTime = useCallback(
		() =>
			timeItems.find((e) => e.enum === (widget?.timePreferance || 'GLOBAL_TIME')),
		[widget],
	);

	const [selectedTime, setSelectedTime] = useState<timePreferance>({
		name: getSelectedTime()?.name || '',
		enum: widget?.timePreferance || 'GLOBAL_TIME',
	});

	const maxMinTime = GetMaxMinTime({
		graphType: widget.panelTypes,
		maxTime,
		minTime,
	});

	const getMinMax = (
		time: timePreferenceType,
	): { min: string | number; max: string | number } => {
		if (time === 'GLOBAL_TIME') {
			const minMax = GetMinMax(globalSelectedTime, [
				minTime / 1000000,
				maxTime / 1000000,
			]);
			return {
				min: convertToNanoSecondsToSecond(minMax.minTime / 1000),
				max: convertToNanoSecondsToSecond(minMax.maxTime / 1000),
			};
		}

		const minMax = getStartAndEndTime({
			type: selectedTime.enum,
			maxTime: maxMinTime.maxTime,
			minTime: maxMinTime.minTime,
		});
		return { min: parseInt(minMax.start, 10), max: parseInt(minMax.end, 10) };
	};

	const queryMinMax = getMinMax(selectedTime.enum);

	const queryLength = widget.query.filter((e) => e.query.length !== 0);

	const response = useQueries(
		queryLength.map((query) => {
			return {
				// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
				queryFn: () => {
					return getQueryResult({
						end: queryMinMax.max.toString(),
						query: query.query,
						start: queryMinMax.min.toString(),
						step: `${getStep({
							start: queryMinMax.min,
							end: queryMinMax.max,
							inputFormat: 's',
						})}`,
					});
				},
				queryHash: `${query.query}-${query.legend}-${selectedTime.enum}`,
				retryOnMount: false,
			};
		}),
	);

	const isError =
		response.find((e) => e?.data?.statusCode !== 200) !== undefined ||
		response.some((e) => e.isError === true);

	const isLoading = response.some((e) => e.isLoading === true);

	const errorMessage = response.find((e) => e.data?.error !== null)?.data?.error;

	const data = response.map((responseOfQuery) =>
		responseOfQuery?.data?.payload?.result.map((e, index) => ({
			query: queryLength[index]?.query,
			queryData: e,
			legend: queryLength[index]?.legend,
		})),
	);

	if (isLoading) {
		return <Spinner height="100%" size="large" tip="Loading..." />;
	}

	if (isError || data === undefined || data[0] === undefined) {
		return (
			<NotFoundContainer>
				<Typography>{errorMessage}</Typography>
			</NotFoundContainer>
		);
	}

	return (
		<>
			{fullViewOptions && (
				<TimeContainer>
					<TimePreference
						{...{
							selectedTime,
							setSelectedTime,
						}}
					/>
					<Button
						onClick={(): void => {
							response.forEach((e) => e.refetch());
						}}
						type="primary"
					>
						Refresh
					</Button>
				</TimeContainer>
			)}

			<GridGraphComponent
				{...{
					GRAPH_TYPES: widget.panelTypes,
					data: getChartData({
						queryData: data.map((e) => ({
							query: e?.map((e) => e.query).join(' ') || '',
							queryData: e?.map((e) => e.queryData) || [],
							legend: e?.map((e) => e.legend).join('') || '',
						})),
					}),
					isStacked: widget.isStacked,
					opacity: widget.opacity,
					title: widget.title,
					onClickHandler,
					name,
					yAxisUnit,
				}}
			/>
		</>
	);
}

interface FullViewProps {
	widget: PromQLWidgets;
	fullViewOptions?: boolean;
	onClickHandler?: GraphOnClickHandler;
	name: string;
	yAxisUnit?: string;
}

FullView.defaultProps = {
	fullViewOptions: undefined,
	onClickHandler: undefined,
	yAxisUnit: undefined,
};

export default FullView;
