/* eslint-disable sonarjs/cognitive-complexity */
import { useEffect, useState } from 'react';
import {
	DragDropContext,
	Draggable,
	Droppable,
	DropResult,
} from 'react-beautiful-dnd';
import { Color } from '@signozhq/design-tokens';
import {
	Button,
	Divider,
	Dropdown,
	Input,
	MenuProps,
	Tooltip,
	Typography,
} from 'antd';
import { FieldDataType } from 'api/v5/v5';
import { SOMETHING_WENT_WRONG } from 'constants/api';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useGetQueryKeySuggestions } from 'hooks/querySuggestions/useGetQueryKeySuggestions';
import { useIsDarkMode } from 'hooks/useDarkMode';
import useDebouncedFn from 'hooks/useDebouncedFunction';
import {
	AlertCircle,
	GripVertical,
	PlusCircle,
	Search,
	Trash2,
} from 'lucide-react';
import { DataSource } from 'types/common/queryBuilder';

import { WidgetGraphProps } from '../types';
import ExplorerAttributeColumns from './ExplorerAttributeColumns';

import './ExplorerColumnsRenderer.styles.scss';

type LogColumnsRendererProps = {
	setSelectedLogFields: WidgetGraphProps['setSelectedLogFields'];
	selectedLogFields: WidgetGraphProps['selectedLogFields'];
	selectedTracesFields: WidgetGraphProps['selectedTracesFields'];
	setSelectedTracesFields: WidgetGraphProps['setSelectedTracesFields'];
};

function ExplorerColumnsRenderer({
	selectedLogFields,
	setSelectedLogFields,
	selectedTracesFields,
	setSelectedTracesFields,
}: LogColumnsRendererProps): JSX.Element {
	const { currentQuery } = useQueryBuilder();
	const [searchText, setSearchText] = useState<string>('');
	const [querySearchText, setQuerySearchText] = useState<string>('');
	const [open, setOpen] = useState<boolean>(false);

	const initialDataSource = currentQuery.builder.queryData[0].dataSource;

	// const { data, isLoading, isError } = useGetAggregateKeys(
	// 	{
	// 		aggregateAttribute: '',
	// 		dataSource: currentQuery.builder.queryData[0].dataSource,
	// 		aggregateOperator: currentQuery.builder.queryData[0].aggregateOperator,
	// 		searchText: querySearchText,
	// 		tagType: '',
	// 	},
	// 	{
	// 		queryKey: [
	// 			currentQuery.builder.queryData[0].dataSource,
	// 			currentQuery.builder.queryData[0].aggregateOperator,
	// 			querySearchText,
	// 		],
	// 	},
	// );

	const { data, isLoading, isError } = useGetQueryKeySuggestions(
		{
			searchText: querySearchText,
			signal: currentQuery.builder.queryData[0].dataSource,
		},
		{
			queryKey: [
				currentQuery.builder.queryData[0].dataSource,
				currentQuery.builder.queryData[0].aggregateOperator,
				querySearchText,
			],
		},
	);

	const isAttributeKeySelected = (key: string): boolean => {
		if (initialDataSource === DataSource.LOGS && selectedLogFields) {
			return selectedLogFields.some((field) => field.name === key);
		}
		if (initialDataSource === DataSource.TRACES && selectedTracesFields) {
			return selectedTracesFields.some((field) => field.name === key);
		}
		return false;
	};

	const handleCheckboxChange = (key: string): void => {
		if (
			initialDataSource === DataSource.LOGS &&
			setSelectedLogFields !== undefined
		) {
			if (selectedLogFields) {
				if (isAttributeKeySelected(key)) {
					setSelectedLogFields(
						selectedLogFields.filter((field) => field.name !== key),
					);
				} else {
					setSelectedLogFields([
						...selectedLogFields,
						{ dataType: 'string', name: key, type: '' },
					]);
				}
			} else {
				setSelectedLogFields([{ dataType: 'string', name: key, type: '' }]);
			}
		} else if (
			initialDataSource === DataSource.TRACES &&
			setSelectedTracesFields !== undefined
		) {
			const selectedField = Object.values(data?.data?.data?.keys || {})
				?.flat()
				?.find((attributeKey) => attributeKey.name === key);

			if (selectedTracesFields) {
				if (isAttributeKeySelected(key)) {
					setSelectedTracesFields(
						selectedTracesFields.filter((field) => field.name !== key),
					);
				} else if (selectedField) {
					setSelectedTracesFields([
						...selectedTracesFields,
						{
							...selectedField,
							fieldDataType: selectedField.fieldDataType as FieldDataType,
						},
					]);
				}
			} else if (selectedField) {
				setSelectedTracesFields([
					{
						...selectedField,
						fieldDataType: selectedField.fieldDataType as FieldDataType,
					},
				]);
			}
		}
		setOpen(false);
	};

	const debouncedSetQuerySearchText = useDebouncedFn((value) => {
		setQuerySearchText(value as string);
	}, 400);

	useEffect(
		() => (): void => {
			debouncedSetQuerySearchText.cancel();
		},
		[debouncedSetQuerySearchText],
	);

	const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
		setSearchText(e.target.value);
		debouncedSetQuerySearchText(e.target.value);
	};

	const items: MenuProps['items'] = [
		{
			key: 'search',
			label: (
				<Input
					type="text"
					placeholder="Search"
					className="explorer-columns-search"
					value={searchText}
					onChange={handleSearchChange}
					prefix={<Search size={16} style={{ padding: '6px' }} />}
				/>
			),
		},
		{
			key: 'columns',
			label: (
				<ExplorerAttributeColumns
					isLoading={isLoading}
					data={data}
					searchText={searchText}
					isAttributeKeySelected={isAttributeKeySelected}
					handleCheckboxChange={handleCheckboxChange}
					dataSource={initialDataSource}
				/>
			),
		},
	];

	const removeSelectedLogField = (name: string): void => {
		if (
			initialDataSource === DataSource.LOGS &&
			setSelectedLogFields &&
			selectedLogFields
		) {
			setSelectedLogFields(
				selectedLogFields.filter((field) => field.name !== name),
			);
		}
		if (
			initialDataSource === DataSource.TRACES &&
			setSelectedTracesFields &&
			selectedTracesFields
		) {
			setSelectedTracesFields(
				selectedTracesFields.filter((field) => field.name !== name),
			);
		}
	};

	const onDragEnd = (result: DropResult): void => {
		if (!result.destination) {
			return;
		}

		if (
			initialDataSource === DataSource.LOGS &&
			selectedLogFields &&
			setSelectedLogFields
		) {
			const items = [...selectedLogFields];
			const [reorderedItem] = items.splice(result.source.index, 1);
			items.splice(result.destination.index, 0, reorderedItem);

			setSelectedLogFields(items);
		}
		if (
			initialDataSource === DataSource.TRACES &&
			selectedTracesFields &&
			setSelectedTracesFields
		) {
			const items = [...selectedTracesFields];
			const [reorderedItem] = items.splice(result.source.index, 1);
			items.splice(result.destination.index, 0, reorderedItem);

			setSelectedTracesFields(items);
		}
	};

	const toggleDropdown = (): void => {
		setOpen(!open);
		if (!open) {
			setSearchText('');
		}
	};

	const isDarkMode = useIsDarkMode();

	return (
		<div className="explorer-columns-renderer">
			<div className="title">
				<Typography.Text>Columns</Typography.Text>
				{isError && (
					<Tooltip title={SOMETHING_WENT_WRONG}>
						<AlertCircle size={16} data-testid="alert-circle-icon" />
					</Tooltip>
				)}
			</div>
			<Divider />
			{!isError && (
				<div className="explorer-columns-contents">
					<DragDropContext onDragEnd={onDragEnd}>
						<Droppable droppableId="drag-drop-list" direction="horizontal">
							{(provided): JSX.Element => (
								<div
									className="explorer-columns"
									{...provided.droppableProps}
									ref={provided.innerRef}
								>
									{initialDataSource === DataSource.LOGS &&
										selectedLogFields &&
										selectedLogFields.map((field, index) => (
											// eslint-disable-next-line react/no-array-index-key
											<Draggable key={index} draggableId={index.toString()} index={index}>
												{(dragProvided): JSX.Element => (
													<div
														className="explorer-column-card"
														ref={dragProvided.innerRef}
														{...dragProvided.draggableProps}
														{...dragProvided.dragHandleProps}
													>
														<div className="explorer-column-title">
															<GripVertical size={12} color="#5A5A5A" />
															{field.name}
														</div>
														<Trash2
															size={12}
															color="red"
															onClick={(): void => removeSelectedLogField(field.name)}
															data-testid="trash-icon"
														/>
													</div>
												)}
											</Draggable>
										))}
									{initialDataSource === DataSource.TRACES &&
										selectedTracesFields &&
										selectedTracesFields.map((field, index) => (
											// eslint-disable-next-line react/no-array-index-key
											<Draggable key={index} draggableId={index.toString()} index={index}>
												{(dragProvided): JSX.Element => (
													<div
														className="explorer-column-card"
														ref={dragProvided.innerRef}
														{...dragProvided.draggableProps}
														{...dragProvided.dragHandleProps}
													>
														<div className="explorer-column-title">
															<GripVertical size={12} color="#5A5A5A" />
															{field?.name || (field as any)?.key}
														</div>
														<Trash2
															size={12}
															color="red"
															onClick={(): void =>
																removeSelectedLogField(field?.name || (field as any)?.key)
															}
															data-testid="trash-icon"
														/>
													</div>
												)}
											</Draggable>
										))}
								</div>
							)}
						</Droppable>
					</DragDropContext>
					<div>
						<Dropdown
							menu={{ items }}
							arrow
							placement="top"
							open={open}
							overlayClassName="explorer-columns-dropdown"
						>
							<Button
								className="action-btn"
								data-testid="add-columns-button"
								icon={
									<PlusCircle
										size={16}
										color={isDarkMode ? Color.BG_INK_400 : Color.BG_VANILLA_100}
									/>
								}
								onClick={toggleDropdown}
							/>
						</Dropdown>
					</div>
				</div>
			)}
		</div>
	);
}

export default ExplorerColumnsRenderer;
