// 📁 MeetingListApp.js
import React, { useEffect, useState, useMemo } from "react";
import Spinner from "../components/common/Spinner";
import moment from "moment";
import axios from "axios";
import Select from 'react-select';
import AsyncSelect from 'react-select/async';
const { __ } = wp.i18n;
import { langString } from "../Helpers";
import { select2Styles } from "../Helpers";

function MeetingListApp({ platform, meeting_type, type }) {
	const [meetings, setMeetings] = useState([]);
	const [loading, setLoading] = useState(true);
	const [sortBy, setSortBy] = useState('');
	const [sortOrder, setSortOrder] = useState('asc');
	const [currentPage, setCurrentPage] = useState(1);
	const [searchQuery, setSearchQuery] = useState('');

	const [visibilityMode, setVisibilityMode] = useState(mhub_frontend_data.visibility_mode || 'all');
	const [selectedRoles, setSelectedRoles] = useState(mhub_frontend_data.selected_roles || []);
	const [selectedUsers, setSelectedUsers] = useState((mhub_frontend_data.selected_users || []).map(String));

	const [allRoles, setAllRoles] = useState([]);
	const [userSearchLoading, setUserSearchLoading] = useState(false);
	const [selectedUserOptions, setSelectedUserOptions] = useState([]);

	const itemsPerPage = 10;

	// Debounced user search function
	const debouncedLoadUsers = useMemo(() => {
		if (!mhub_frontend_data.is_admin) return () => { };

		let timeoutId;
		return (inputValue, callback) => {
			clearTimeout(timeoutId);
			timeoutId = setTimeout(async () => {
				if (!inputValue || inputValue.length < 2) {
					callback([]);
					return;
				}

				try {
					setUserSearchLoading(true);
					const formData = new FormData();
					formData.append('action', 'mhub_fetch_users');
					formData.append('nonce', mhub_frontend_data.nonce);
					formData.append('search', inputValue);

					const response = await axios.post(mhub_frontend_data.ajax_url, formData);

					if (response.data.success) {
						callback(response.data.data || []);
					} else {
						callback([]);
					}
				} catch (error) {
					console.error("Failed to load users", error);
					callback([]);
				} finally {
					setUserSearchLoading(false);
				}
			}, 300); // 300ms debounce
		};
	}, []);

	// Load user options for AsyncSelect
	const loadUserOptions = async (inputValue = '') => {
		if (!mhub_frontend_data.is_admin) return () => { };

		if (!inputValue || inputValue.length < 2) {
			return [];
		}

		try {
			const formData = new FormData();
			formData.append('action', 'mhub_fetch_users');
			formData.append('nonce', mhub_frontend_data.nonce);
			formData.append('search', inputValue);

			const response = await axios.post(mhub_frontend_data.ajax_url, formData);

			if (response.data.success) {
				return response.data.data || [];
			}
			return [];
		} catch (error) {
			console.error("Failed to load users", error);
			return [];
		}
	};

	// Fetch selected users details on component mount
	useEffect(() => {
		if (!mhub_frontend_data.is_admin) return;
		const fetchSelectedUsersDetails = async () => {
			if (selectedUsers.length === 0) {
				setSelectedUserOptions([]);
				return;
			}

			try {
				const formData = new FormData();
				formData.append('action', 'mhub_fetch_users_by_ids');
				formData.append('nonce', mhub_frontend_data.nonce);
				selectedUsers.forEach(userId => {
					formData.append('user_ids[]', userId);
				});

				const response = await axios.post(mhub_frontend_data.ajax_url, formData);
				if (response.data.success) {
					setSelectedUserOptions(response.data.data || []);
				}
			} catch (error) {
				console.error("Error fetching selected users by ID", error);
			}
		};


		if (visibilityMode === 'user') {
			fetchSelectedUsersDetails();
		}
	}, [selectedUsers, visibilityMode]);

	// Fetch meetings when any key state changes
	useEffect(() => {
		const fetchData = async () => {
			try {
				setLoading(true);
				const formData = new FormData();
				formData.append('action', 'mhub_meeting_list');
				formData.append('nonce', mhub_frontend_data.nonce);
				formData.append('page_id', mhub_frontend_data.page_id);
				formData.append('visibility_mode', visibilityMode);
				formData.append('roles', JSON.stringify(selectedRoles));
				formData.append('users', JSON.stringify(selectedUsers));
				formData.append('use_passed_values', '1');

				const response = await axios.post(mhub_frontend_data.ajax_url, formData);



				if (response.data.success && Array.isArray(response.data.data)) {
					const filtered = response.data.data.filter(meeting => {
						if (platform === "zoom") {
							return meeting.settings.selected_platform === platform && meeting.settings.meeting_type === meeting_type;
						}
						return meeting.settings.selected_platform === platform;
					});
					setMeetings(filtered);
				}
			} catch (error) {
				console.error(langString('error_fetching_data'), error);
			} finally {
				setLoading(false);
			}
		};

		fetchData();
	}, [platform, meeting_type, visibilityMode, selectedRoles, selectedUsers]);

	// Fetch roles when mode is 'role'
	useEffect(() => {
		if (!mhub_frontend_data.is_admin) return;

		if (visibilityMode === 'role') {
			const fetchRoles = async () => {
				try {
					const formData = new FormData();
					formData.append('action', 'mhub_fetch_roles');
					formData.append('nonce', mhub_frontend_data.nonce);
					const response = await axios.post(mhub_frontend_data.ajax_url, formData);
					if (response.data.success) {
						setAllRoles(response.data.data);
					}
				} catch (error) {
					console.error("Failed to load roles", error);
				}
			};
			fetchRoles();
		}
	}, [visibilityMode]);

	// Sorting
	const handleSort = (column) => {
		if (sortBy === column) setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc');
		else {
			setSortBy(column);
			setSortOrder('asc');
		}
	};

	const getSortableValue = (meeting, column) => {
		switch (column) {
			case 'title': return meeting.title;
			case 'date': return moment(meeting.date).format("YYYY-MM-DD HH:mm");
			default: return '';
		}
	};

	const getSortedMeetings = () => {
		return [...meetings].sort((a, b) => {
			const aVal = getSortableValue(a, sortBy);
			const bVal = getSortableValue(b, sortBy);
			return sortOrder === 'asc' ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
		});
	};

	// Filters and Pagination
	const filteredMeetings = getSortedMeetings()
		.filter(meeting => {
			if (type === 'upcoming') {
				return meeting.settings && meeting.settings.startDateTime && moment(meeting.settings.startDateTime).isAfter(moment());
			}
			if (type === 'available') {
				// A meeting is "available" when it has not been manually ended
				// AND is either recurring (always has a future occurrence) or has a future start time.
				const isEnded = meeting.settings && meeting.settings.mhub_meeting_status === 'end';
				if (isEnded) return false;

				const isRecurring = meeting.settings && meeting.settings.enable_recurring_meeting;
				if (isRecurring) return true; // Recurring meetings are always available unless ended.

				// For one-off / scheduled meetings: only show if start time is in the future.
				return meeting.settings && meeting.settings.startDateTime && moment(meeting.settings.startDateTime).isAfter(moment());
			}
			return true;
		})
		.filter(meeting =>
			meeting.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
			moment(meeting.date).format("MMMM Do YYYY").toLowerCase().includes(searchQuery.toLowerCase())
		);


	const indexOfLastItem = currentPage * itemsPerPage;
	const indexOfFirstItem = indexOfLastItem - itemsPerPage;
	const currentMeetings = filteredMeetings.slice(indexOfFirstItem, indexOfLastItem);
	const totalPages = Math.ceil(filteredMeetings.length / itemsPerPage);

	const handlePageChange = (page) => {
		if (page >= 1 && page <= totalPages) setCurrentPage(page);
	};

	// Visibility Control
	const handleChangeVisibility = (mode) => {
		setVisibilityMode(mode);
		setCurrentPage(1);
		saveVisibilitySettings(mode, selectedRoles, selectedUsers);
	};

	// Updated handler for react-select role change
	const handleRoleChange = (selectedOptions) => {
		const roleValues = selectedOptions ? selectedOptions.map(option => option.value) : [];
		setSelectedRoles(roleValues);
		setCurrentPage(1);
		saveVisibilitySettings(visibilityMode, roleValues, selectedUsers);
	};

	// Updated handler for react-select user change with AsyncSelect
	const handleUserChange = (selectedOptions) => {
		const userValues = selectedOptions ? selectedOptions.map(option => String(option.value)) : [];
		setSelectedUsers(userValues);
		setSelectedUserOptions(selectedOptions || []);
		setCurrentPage(1);
		saveVisibilitySettings(visibilityMode, selectedRoles, userValues);
	};

	const saveVisibilitySettings = async (mode, roles, users) => {
		try {
			const formData = new FormData();
			formData.append('action', 'mhub_save_visibility_mode');
			formData.append('nonce', mhub_frontend_data.nonce);
			formData.append('page_id', mhub_frontend_data.page_id);
			formData.append('mode', mode);
			formData.append('roles', JSON.stringify(roles));
			formData.append('users', JSON.stringify(users));
			await axios.post(mhub_frontend_data.ajax_url, formData);
		} catch (error) {
			console.error("Error saving visibility settings", error);
		}
	};

	// Helper function to get selected role options for react-select
	const getSelectedRoleOptions = () => {
		return allRoles.filter(role => selectedRoles.includes(role.value));
	};

	// Language strings for user search
	const getUserSearchStrings = () => ({
		loadingMessage: () => __('Loading users...', 'meetinghub'),
		noOptionsMessage: ({ inputValue }) =>
			!inputValue || inputValue.length < 2
				? __('Type at least 2 characters to search users', 'meetinghub')
				: __('No users found', 'meetinghub'),
		placeholder: __('Search users by name, username, or email...', 'meetinghub')
	});

	if (loading) return <Spinner />;



	return (
		<div id="meeting_hub">
			<div className="mhub-common-dashboard">
				<div className="mhub-table-wrapper">
					{meetings.length > 0 && (
						<div className="search-container">
							<input
								type="text"
								placeholder={langString('search')}
								value={searchQuery}
								onChange={(e) => setSearchQuery(e.target.value)}
								className="search-input"
							/>
						</div>
					)}

					{platform === 'msteams' && mhub_frontend_data.is_admin && meetings.some(m => !m.join_link && m.view_in_calendar_link) && (
						<div style={{
							backgroundColor: '#fff3cd',
							color: '#856404',
							padding: '10px',
							marginBottom: '15px',
							borderRadius: '4px',
							border: '1px solid #ffeeba',
							fontSize: '14px',
							clear: 'both',
							marginLeft: '20px',
							marginRight: '20px'
						}}>
							{langString('admin_note_personal_account_details')}
						</div>
					)}

					<div className={meetings.length ? 'meetinghub-meeting-list' : 'meetinghub-no-meeting'}>
						{meetings.length > 0 ? (
							<div className="table-container">
								<table className="meeting-hub-table">
									<thead>
										<tr>
											<th onClick={() => handleSort('title')} className={sortBy === 'title' ? `sortable ${sortOrder}` : 'sortable'}>{langString('topic')}</th>
											<th onClick={() => handleSort('date')} className={sortBy === 'date' ? `sortable ${sortOrder}` : 'sortable'}>{langString('start_time')}</th>
											<th>{langString('actions')}</th>
										</tr>
									</thead>
									<tbody>
										{currentMeetings.map((meeting) => {
											const { id, title, settings, join_link, view_in_calendar_link } = meeting;
											return (
												<tr key={id}>
													<td>{title}</td>
													<td>{moment(settings.startDateTime).format("dddd, MMMM D, YYYY h:mm A")}</td>
													<td>
														{platform === 'msteams' ? (
															<>
																{join_link ? (
																	<button className="action-btn action-text-btn" onClick={() => window.open(join_link, '_blank')}>
																		{langString('join_meeting')}
																	</button>
																) : view_in_calendar_link ? (
																	<button className="action-btn action-text-btn" onClick={() => window.open(view_in_calendar_link, '_blank')}>
																		{langString('view_in_calendar')}
																	</button>
																) : (
																	<span style={{ fontSize: '12px', color: '#999' }}>{__('No link available', 'meetinghub')}</span>
																)}
															</>
														) : (
															<button className="action-btn action-text-btn" onClick={() => window.open(settings.url, '_blank')}>
																{langString('meeting_link')}
															</button>
														)}
													</td>
												</tr>
											);
										})}
									</tbody>
								</table>
							</div>
						) : (
							<div className="empty-meeting-wrapper">
								<h1>{platform === "zoom" && meeting_type == 1 ? langString('no_webinar') : langString('no_meetings')}</h1>
							</div>
						)}

						{!filteredMeetings.length && meetings.length > 0 && (
							<div className="empty-meeting-wrapper">
								<p>{langString('no_records')}</p>
							</div>
						)}

						{meetings.length > itemsPerPage && (
							<div className="pagination">
								<span className={`page-link ${currentPage === 1 ? 'disabled' : ''}`} onClick={() => handlePageChange(currentPage - 1)}>&lt; {langString('previous')}</span>
								{[...Array(totalPages).keys()].map((page) => (
									<span key={page + 1} className={`page-link ${currentPage === page + 1 ? 'active' : ''}`} onClick={() => handlePageChange(page + 1)}>{page + 1}</span>
								))}
								<span className={`page-link ${currentPage === totalPages ? 'disabled' : ''}`} onClick={() => handlePageChange(currentPage + 1)}>{langString('next')} &gt;</span>
							</div>
						)}
					</div>
				</div>

				{mhub_frontend_data.is_admin && (
					<div className={`meetinghub-visibility-control ${loading ? 'loading' : ''}`}>
						<div className="visibility-main-control">
							<label>{langString('meeting_visibility')}</label>
							<select value={visibilityMode} onChange={(e) => handleChangeVisibility(e.target.value)} className="visibility-select">
								<option value="all">{platform === "zoom" && meeting_type == 1 ? langString('show_all_webinars') : langString('show_all_meetings')}</option>
								<option value="user">{langString('user_specific')}</option>
								<option value="role">{langString('role_based')}</option>
							</select>
						</div>

						{(visibilityMode === 'role' || visibilityMode === 'user') && (
							<div className="visibility-sub-controls">
								{visibilityMode === 'role' && (
									<div className="visibility-roles">
										<label>{langString('select_roles')}</label>
										<Select
											options={allRoles}
											value={getSelectedRoleOptions()}
											onChange={handleRoleChange}
											isMulti
											className="mhub-select2"
											placeholder={langString('select_roles')}
											styles={select2Styles()}
											isClearable
										/>
									</div>
								)}

								{visibilityMode === 'user' && (
									<div className="visibility-users">
										<label>{langString('select_users')}</label>
										<AsyncSelect
											cacheOptions
											loadOptions={debouncedLoadUsers}
											defaultOptions={false}
											value={selectedUserOptions}
											onChange={handleUserChange}
											isMulti
											className="mhub-select2"
											placeholder={getUserSearchStrings().placeholder}
											styles={select2Styles()}
											isClearable
											isLoading={userSearchLoading}
											loadingMessage={getUserSearchStrings().loadingMessage}
											noOptionsMessage={getUserSearchStrings().noOptionsMessage}
											filterOption={() => true} // Disable client-side filtering
											menuPortalTarget={document.body}
											menuPosition={'fixed'}
											// Minimum input length handled in loadOptions
											onInputChange={(inputValue, actionMeta) => {
												if (actionMeta.action === 'input-change') {
													return inputValue;
												}
											}}
										/>
									</div>
								)}
							</div>
						)}
					</div>
				)}
			</div>
		</div >
	);
}

export default MeetingListApp;