/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import './RightContainer.styles.scss';

import type { InputRef } from 'antd';
import {
	AutoComplete,
	Input,
	InputNumber,
	Select,
	Space,
	Switch,
	Typography,
} from 'antd';
import TimePreference from 'components/TimePreferenceDropDown';
import { PANEL_TYPES, PanelDisplay } from 'constants/queryBuilder';
import GraphTypes, {
	ItemsProps,
} from 'container/NewDashboard/ComponentsSlider/menuItems';
import useCreateAlerts from 'hooks/queryBuilder/useCreateAlerts';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { ConciergeBell, LineChart, Plus, Spline } from 'lucide-react';
import { useDashboard } from 'providers/Dashboard/Dashboard';
import {
	Dispatch,
	SetStateAction,
	useCallback,
	useEffect,
	useMemo,
	useRef,
	useState,
} from 'react';
import { UseQueryResult } from 'react-query';
import { SuccessResponse } from 'types/api';
import {
	ColumnUnit,
	LegendPosition,
	Widgets,
} from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { DataSource } from 'types/common/queryBuilder';
import { popupContainer } from 'utils/selectPopupContainer';

import { ColumnUnitSelector } from './ColumnUnitSelector/ColumnUnitSelector';
import {
	panelTypeVsBucketConfig,
	panelTypeVsColumnUnitPreferences,
	panelTypeVsCreateAlert,
	panelTypeVsFillSpan,
	panelTypeVsLegendColors,
	panelTypeVsLegendPosition,
	panelTypeVsLogScale,
	panelTypeVsPanelTimePreferences,
	panelTypeVsSoftMinMax,
	panelTypeVsStackingChartPreferences,
	panelTypeVsThreshold,
	panelTypeVsYAxisUnit,
} from './constants';
import LegendColors from './LegendColors/LegendColors';
import ThresholdSelector from './Threshold/ThresholdSelector';
import { ThresholdProps } from './Threshold/types';
import { timePreferance } from './timeItems';
import YAxisUnitSelector from './YAxisUnitSelector';

const { TextArea } = Input;
const { Option } = Select;

enum LogScale {
	LINEAR = 'linear',
	LOGARITHMIC = 'logarithmic',
}

interface VariableOption {
	value: string;
	label: string;
}

// eslint-disable-next-line sonarjs/cognitive-complexity
function RightContainer({
	description,
	setDescription,
	setTitle,
	title,
	selectedGraph,
	bucketCount,
	bucketWidth,
	stackedBarChart,
	setStackedBarChart,
	setBucketCount,
	setBucketWidth,
	setSelectedTime,
	selectedTime,
	yAxisUnit,
	setYAxisUnit,
	setGraphHandler,
	thresholds,
	combineHistogram,
	setCombineHistogram,
	setThresholds,
	selectedWidget,
	isFillSpans,
	setIsFillSpans,
	softMax,
	softMin,
	setSoftMax,
	setSoftMin,
	columnUnits,
	setColumnUnits,
	isLogScale,
	setIsLogScale,
	legendPosition,
	setLegendPosition,
	customLegendColors,
	setCustomLegendColors,
	queryResponse,
}: RightContainerProps): JSX.Element {
	const { selectedDashboard } = useDashboard();
	const [inputValue, setInputValue] = useState(title);
	const [autoCompleteOpen, setAutoCompleteOpen] = useState(false);
	const [cursorPos, setCursorPos] = useState(0);
	const inputRef = useRef<InputRef>(null);

	const onChangeHandler = useCallback(
		(setFunc: Dispatch<SetStateAction<string>>, value: string) => {
			setFunc(value);
		},
		[],
	);

	const selectedGraphType =
		GraphTypes.find((e) => e.name === selectedGraph)?.display || '';

	const onCreateAlertsHandler = useCreateAlerts(selectedWidget, 'panelView');

	const allowThreshold = panelTypeVsThreshold[selectedGraph];
	const allowSoftMinMax = panelTypeVsSoftMinMax[selectedGraph];
	const allowFillSpans = panelTypeVsFillSpan[selectedGraph];
	const allowLogScale = panelTypeVsLogScale[selectedGraph];
	const allowYAxisUnit = panelTypeVsYAxisUnit[selectedGraph];
	const allowCreateAlerts = panelTypeVsCreateAlert[selectedGraph];
	const allowBucketConfig = panelTypeVsBucketConfig[selectedGraph];
	const allowStackingBarChart =
		panelTypeVsStackingChartPreferences[selectedGraph];
	const allowPanelTimePreference =
		panelTypeVsPanelTimePreferences[selectedGraph];
	const allowLegendPosition = panelTypeVsLegendPosition[selectedGraph];
	const allowLegendColors = panelTypeVsLegendColors[selectedGraph];

	const allowPanelColumnPreference =
		panelTypeVsColumnUnitPreferences[selectedGraph];

	const { currentQuery } = useQueryBuilder();

	const [graphTypes, setGraphTypes] = useState<ItemsProps[]>(GraphTypes);

	// Get dashboard variables
	const dashboardVariables = useMemo<VariableOption[]>(() => {
		if (!selectedDashboard?.data?.variables) return [];
		return Object.entries(selectedDashboard.data.variables).map(([, value]) => ({
			value: value.name || '',
			label: value.name || '',
		}));
	}, [selectedDashboard?.data?.variables]);

	const updateCursorAndDropdown = (value: string, pos: number): void => {
		setCursorPos(pos);
		const lastDollar = value.lastIndexOf('$', pos - 1);
		setAutoCompleteOpen(lastDollar !== -1 && pos >= lastDollar + 1);
	};

	const onInputChange = (value: string): void => {
		setInputValue(value);
		onChangeHandler(setTitle, value);
		setTimeout(() => {
			const pos = inputRef.current?.input?.selectionStart ?? 0;
			updateCursorAndDropdown(value, pos);
		}, 0);
	};

	const handleInputCursor = (): void => {
		const pos = inputRef.current?.input?.selectionStart ?? 0;
		updateCursorAndDropdown(inputValue, pos);
	};

	const onSelect = (selectedValue: string): void => {
		const pos = cursorPos;
		const value = inputValue;
		const lastDollar = value.lastIndexOf('$', pos - 1);
		const textBeforeDollar = value.substring(0, lastDollar);
		const textAfterDollar = value.substring(lastDollar + 1);
		const match = textAfterDollar.match(/^([a-zA-Z0-9_.]*)/);
		const rest = textAfterDollar.substring(match ? match[1].length : 0);
		const newValue = `${textBeforeDollar}$${selectedValue}${rest}`;
		setInputValue(newValue);
		onChangeHandler(setTitle, newValue);
		setAutoCompleteOpen(false);
		setTimeout(() => {
			const newCursor = `${textBeforeDollar}$${selectedValue}`.length;
			inputRef.current?.input?.setSelectionRange(newCursor, newCursor);
			setCursorPos(newCursor);
		}, 0);
	};

	const filterOption = (
		inputValue: string,
		option?: VariableOption,
	): boolean => {
		const pos = cursorPos;
		const value = inputValue;
		const lastDollar = value.lastIndexOf('$', pos - 1);
		if (lastDollar === -1) return false;
		const afterDollar = value.substring(lastDollar + 1, pos).toLowerCase();
		return option?.value.toLowerCase().startsWith(afterDollar) || false;
	};

	useEffect(() => {
		const queryContainsMetricsDataSource = currentQuery.builder.queryData.some(
			(query) => query.dataSource === DataSource.METRICS,
		);

		if (queryContainsMetricsDataSource) {
			setGraphTypes((prev) =>
				prev.filter((graph) => graph.name !== PANEL_TYPES.LIST),
			);
		} else {
			setGraphTypes(GraphTypes);
		}
	}, [currentQuery]);

	const softMinHandler = useCallback(
		(value: number | null) => {
			setSoftMin(value);
		},
		[setSoftMin],
	);

	const softMaxHandler = useCallback(
		(value: number | null) => {
			setSoftMax(value);
		},
		[setSoftMax],
	);

	return (
		<div className="right-container">
			<section className="header">
				<div className="purple-dot" />
				<Typography.Text className="header-text">Panel details</Typography.Text>
			</section>
			<section className="name-description">
				<Typography.Text className="typography">Name</Typography.Text>
				<AutoComplete
					options={dashboardVariables}
					value={inputValue}
					onChange={onInputChange}
					onSelect={onSelect}
					filterOption={filterOption}
					style={{ width: '100%' }}
					getPopupContainer={popupContainer}
					placeholder="Enter the panel name here..."
					open={autoCompleteOpen}
				>
					<Input
						rootClassName="name-input"
						ref={inputRef}
						onSelect={handleInputCursor}
						onClick={handleInputCursor}
						onBlur={(): void => setAutoCompleteOpen(false)}
					/>
				</AutoComplete>
				<Typography.Text className="typography">Description</Typography.Text>
				<TextArea
					placeholder="Enter the panel description here..."
					bordered
					allowClear
					value={description}
					onChange={(event): void =>
						onChangeHandler(setDescription, event.target.value)
					}
					rootClassName="description-input"
				/>
			</section>
			<section className="panel-config">
				<Typography.Text className="typography">Panel Type</Typography.Text>
				<Select
					onChange={setGraphHandler}
					value={selectedGraph}
					style={{ width: '100%' }}
					className="panel-type-select"
					data-testid="panel-change-select"
				>
					{graphTypes.map((item) => (
						<Option key={item.name} value={item.name}>
							<div className="select-option">
								<div className="icon">{item.icon}</div>
								<Typography.Text className="display">{item.display}</Typography.Text>
							</div>
						</Option>
					))}
				</Select>

				{allowFillSpans && (
					<Space className="fill-gaps">
						<Typography className="fill-gaps-text">Fill gaps</Typography>
						<Switch
							checked={isFillSpans}
							size="small"
							onChange={(checked): void => setIsFillSpans(checked)}
						/>
					</Space>
				)}

				{allowPanelTimePreference && (
					<>
						<Typography.Text className="panel-time-text">
							Panel Time Preference
						</Typography.Text>
						<TimePreference
							{...{
								selectedTime,
								setSelectedTime,
							}}
						/>
					</>
				)}

				{allowPanelColumnPreference && (
					<ColumnUnitSelector
						columnUnits={columnUnits}
						setColumnUnits={setColumnUnits}
					/>
				)}

				{allowYAxisUnit && (
					<YAxisUnitSelector
						defaultValue={yAxisUnit}
						onSelect={setYAxisUnit}
						fieldLabel={
							selectedGraphType === PanelDisplay.VALUE ||
							selectedGraphType === PanelDisplay.PIE
								? 'Unit'
								: 'Y Axis Unit'
						}
					/>
				)}
				{allowSoftMinMax && (
					<section className="soft-min-max">
						<section className="container">
							<Typography.Text className="text">Soft Min</Typography.Text>
							<InputNumber
								type="number"
								value={softMin}
								onChange={softMinHandler}
								rootClassName="input"
							/>
						</section>
						<section className="container">
							<Typography.Text className="text">Soft Max</Typography.Text>
							<InputNumber
								value={softMax}
								type="number"
								rootClassName="input"
								onChange={softMaxHandler}
							/>
						</section>
					</section>
				)}

				{allowStackingBarChart && (
					<section className="stack-chart">
						<Typography.Text className="label">Stack series</Typography.Text>
						<Switch
							checked={stackedBarChart}
							size="small"
							onChange={(checked): void => setStackedBarChart(checked)}
						/>
					</section>
				)}

				{allowBucketConfig && (
					<section className="bucket-config">
						<Typography.Text className="label">Number of buckets</Typography.Text>
						<InputNumber
							value={bucketCount || null}
							type="number"
							min={0}
							rootClassName="bucket-input"
							placeholder="Default: 30"
							onChange={(val): void => {
								setBucketCount(val || 0);
							}}
						/>
						<Typography.Text className="label bucket-size-label">
							Bucket width
						</Typography.Text>
						<InputNumber
							value={bucketWidth || null}
							type="number"
							precision={2}
							placeholder="Default: Auto"
							step={0.1}
							min={0.0}
							rootClassName="bucket-input"
							onChange={(val): void => {
								setBucketWidth(val || 0);
							}}
						/>
						<section className="combine-hist">
							<Typography.Text className="label">
								Merge all series into one
							</Typography.Text>
							<Switch
								checked={combineHistogram}
								size="small"
								onChange={(checked): void => setCombineHistogram(checked)}
							/>
						</section>
					</section>
				)}

				{allowLogScale && (
					<section className="log-scale">
						<Typography.Text className="typography">Y Axis Scale</Typography.Text>
						<Select
							onChange={(value): void => setIsLogScale(value === LogScale.LOGARITHMIC)}
							value={isLogScale ? LogScale.LOGARITHMIC : LogScale.LINEAR}
							style={{ width: '100%' }}
							className="panel-type-select"
							defaultValue={LogScale.LINEAR}
						>
							<Option value={LogScale.LINEAR}>
								<div className="select-option">
									<div className="icon">
										<LineChart size={16} />
									</div>
									<Typography.Text className="display">Linear</Typography.Text>
								</div>
							</Option>
							<Option value={LogScale.LOGARITHMIC}>
								<div className="select-option">
									<div className="icon">
										<Spline size={16} />
									</div>
									<Typography.Text className="display">Logarithmic</Typography.Text>
								</div>
							</Option>
						</Select>
					</section>
				)}

				{allowLegendPosition && (
					<section className="legend-position">
						<Typography.Text className="typography">Legend Position</Typography.Text>
						<Select
							onChange={(value: LegendPosition): void => setLegendPosition(value)}
							value={legendPosition}
							style={{ width: '100%' }}
							className="panel-type-select"
							defaultValue={LegendPosition.BOTTOM}
						>
							<Option value={LegendPosition.BOTTOM}>
								<div className="select-option">
									<Typography.Text className="display">Bottom</Typography.Text>
								</div>
							</Option>
							<Option value={LegendPosition.RIGHT}>
								<div className="select-option">
									<Typography.Text className="display">Right</Typography.Text>
								</div>
							</Option>
						</Select>
					</section>
				)}

				{allowLegendColors && (
					<section className="legend-colors">
						<LegendColors
							customLegendColors={customLegendColors}
							setCustomLegendColors={setCustomLegendColors}
							queryResponse={queryResponse}
						/>
					</section>
				)}
			</section>

			{allowCreateAlerts && (
				<section className="alerts" onClick={onCreateAlertsHandler}>
					<div className="left-section">
						<ConciergeBell size={14} className="bell-icon" />
						<Typography.Text className="alerts-text">Alerts</Typography.Text>
					</div>
					<Plus size={14} className="plus-icon" />
				</section>
			)}

			{allowThreshold && (
				<section>
					<ThresholdSelector
						thresholds={thresholds}
						setThresholds={setThresholds}
						yAxisUnit={yAxisUnit}
						selectedGraph={selectedGraph}
						columnUnits={columnUnits}
					/>
				</section>
			)}
		</div>
	);
}

interface RightContainerProps {
	title: string;
	setTitle: Dispatch<SetStateAction<string>>;
	description: string;
	setDescription: Dispatch<SetStateAction<string>>;
	stacked: boolean;
	setStacked: Dispatch<SetStateAction<boolean>>;
	opacity: string;
	setOpacity: Dispatch<SetStateAction<string>>;
	selectedNullZeroValue: string;
	setSelectedNullZeroValue: Dispatch<SetStateAction<string>>;
	selectedGraph: PANEL_TYPES;
	setSelectedTime: Dispatch<SetStateAction<timePreferance>>;
	selectedTime: timePreferance;
	yAxisUnit: string;
	stackedBarChart: boolean;
	setStackedBarChart: Dispatch<SetStateAction<boolean>>;
	bucketWidth: number;
	bucketCount: number;
	combineHistogram: boolean;
	setCombineHistogram: Dispatch<SetStateAction<boolean>>;
	setBucketWidth: Dispatch<SetStateAction<number>>;
	setBucketCount: Dispatch<SetStateAction<number>>;
	setYAxisUnit: Dispatch<SetStateAction<string>>;
	setGraphHandler: (type: PANEL_TYPES) => void;
	thresholds: ThresholdProps[];
	setThresholds: Dispatch<SetStateAction<ThresholdProps[]>>;
	selectedWidget?: Widgets;
	isFillSpans: boolean;
	setIsFillSpans: Dispatch<SetStateAction<boolean>>;
	softMin: number | null;
	softMax: number | null;
	columnUnits: ColumnUnit;
	setColumnUnits: Dispatch<SetStateAction<ColumnUnit>>;
	setSoftMin: Dispatch<SetStateAction<number | null>>;
	setSoftMax: Dispatch<SetStateAction<number | null>>;
	isLogScale: boolean;
	setIsLogScale: Dispatch<SetStateAction<boolean>>;
	legendPosition: LegendPosition;
	setLegendPosition: Dispatch<SetStateAction<LegendPosition>>;
	customLegendColors: Record<string, string>;
	setCustomLegendColors: Dispatch<SetStateAction<Record<string, string>>>;
	queryResponse?: UseQueryResult<
		SuccessResponse<MetricRangePayloadProps, unknown>,
		Error
	>;
}

RightContainer.defaultProps = {
	selectedWidget: undefined,
	queryResponse: null,
};

export default RightContainer;
