import TaskElement from './TaskElement';
import { __ } from '@wordpress/i18n';
import useTasks from '@/store/useTasksStore';
import { useEffect } from 'react';
import { LiveVisitorTaskElement } from '@/components/Dashboard/LiveVisitorTaskElement';
import { AnimatePresence, motion, Variants } from 'framer-motion';
import { listSlideAnimation } from './listAnimations';

/**
 * Loading component to show while tasks are being fetched
 *
 * @return { React.ReactElement } Loading component
 */
const LoadingComponent = (): React.ReactElement => {
	const loadingTask: TaskProp = {
		id: 'loading',
		condition: {
			type: 'system',
			function: 'loading'
		},
		msg: __( 'Loading tasks…', 'burst-statistics' ),
		icon: 'skeleton',
		dismissible: false,
		plusone: false,
		label: __( 'Loading…', 'burst-statistics' )
	};

    // eslint-disable-next-line @typescript-eslint/no-empty-function
	return <TaskElement task={loadingTask} onCloseTaskHandler={() => {}} />;
};

/**
 * No tasks component to show when there are no tasks to display
 *
 * @return { React.ReactElement } No tasks component
 */
const NoTasksComponent = (): React.ReactElement => {
	const completedTask: TaskProp = {
		id: 'no-tasks',
		condition: {
			type: 'system',
			function: 'completed'
		},
		msg: __( 'No remaining tasks to show', 'burst-statistics' ),
		icon: 'completed',
		dismissible: false,
		plusone: false,
		label: __( 'Completed', 'burst-statistics' )
	};

    // eslint-disable-next-line @typescript-eslint/no-empty-function
	return <TaskElement task={completedTask} onCloseTaskHandler={() => {}} />;
};

export type TaskProp = {
	id: string;
	condition: {
		type: string;
		function: string;
	};
	msg?: string;
	icon: string;
	dismissible: boolean;
	plusone: boolean;
	label?: string;
	status?: string;
	url?: string;
	fix?: string;
};

/**
 * Tasks component to display list of tasks or loading/no tasks message
 *
 * @return { React.ReactElement | Array< React.ReactElement > } Tasks component or list of TaskElement components
 */
const Tasks = (): React.ReactElement | Array<React.ReactElement> => {
	const tasks = useTasks( ( state ) => state.tasks );
	const loading = useTasks( ( state ) => state.loading );
	const getTasks = useTasks( ( state ) => state.getTasks );

	useEffect(

		/**
		 * Fetch tasks on component mount and when getTasks changes.
		 */
		() => {
			getTasks();
		},
		[ getTasks ]
	);

	if ( loading ) {
		return <LoadingComponent />;
	}

	const clientTasks = tasks.filter( ( task: TaskProp ) => {
		return 'clientside' === task.condition.type;
	});

	const serverTasks = tasks.filter( ( task: TaskProp ) => {
		return 'clientside' !== task.condition.type;
	});

	return (
		<AnimatePresence mode="popLayout">
			<ClientTasks key='client-tasks' tasks={clientTasks} />
			<ServerTasks key='server-tasks' tasks={serverTasks} />
		</AnimatePresence>
	);
};

/**
 * ServerTasks component to display server-side tasks or no tasks message
 *
 * @param { Object } props       - Component props
 * @param { Array }  props.tasks - List of server-side tasks
 *
 * @return { React.ReactElement | Array< React.ReactElement > } NoTasksComponent or list of TaskElement components
 */
const ServerTasks = ({ tasks }: { tasks: TaskProp[] }) => {
    const dismissTask = useTasks( ( state ) => state.dismissTask );

	if ( 0 === tasks.length ) {
		return (
			<motion.div
				key="no-tasks"
				variants={listSlideAnimation( 1 ) as Variants}
				initial="initial"
				animate="animate"
				exit="exit"
			>
				<NoTasksComponent />
			</motion.div>
		);
	}

	return tasks.map( ( task: TaskProp, index: number ) => {
		return (
			<motion.div
				layout
				key={'task-' + index + task.id}
				variants={listSlideAnimation( index ) as Variants}
				initial="initial"
				animate="animate"
				exit="exit"
			>
				<TaskElement
					key={task.id}
					task={task}
					onCloseTaskHandler={() => dismissTask( task.id )}
				/>
			</motion.div>
		);
	});
};

/**
 * ClientTasks component to display client-side tasks
 *
 * @param { Object } props       - Component props
 * @param { Array }  props.tasks - List of client-side tasks
 *
 * @return { Array< React.ReactElement > } List of TaskElement components
 */
const ClientTasks = ({ tasks }: { tasks: TaskProp[] }) => {
	return tasks.map( ( task: TaskProp, index: number ) => {
		if ( 'live_visitors' === task.id ) {
			return (
				<motion.div
					layout
					key={task.id + index}
					variants={listSlideAnimation( index ) as Variants}
					initial="initial"
					animate="animate"
					exit="exit"
				>
					<LiveVisitorTaskElement task={task} />
				</motion.div>
			);
		}

		return (
			<motion.div
				layout
				key={task.id}
				variants={listSlideAnimation( index ) as Variants}
				initial="initial"
				animate="animate"
				exit="exit"
			>
                { /* eslint-disable-next-line @typescript-eslint/no-empty-function */ }
				<TaskElement task={task} onCloseTaskHandler={() => {}} />
			</motion.div>
		);
	});
};

export default Tasks;
