import React, { ChangeEvent, useEffect, useState } from 'react'
import useUser from '../api/hooks/useUser';
import { QueryClient, useQuery, useQueryClient } from 'react-query';
import { userQueryKey } from '../components/common/UserShortComponent';
import MediaInfoEditComponent from '../components/common/edit/MediaInfoEditComponent';
import { MediaInfoType } from '../api/models/Types';
import { userClient } from '../api/axios';
import { AxiosRequestConfig } from 'axios';
import { DeleteAllSessions, DeleteAvatar, DeleteSession, GetSessions, SetAvatar, SetBirthDate, SetLanguage, SetUserInformation } from '../api/UserApi';
import { BirthDateEditModel, DeleteSessionModel, LanguageEditModel, SessionModel, UserInformationEditModel } from '../api/models/AccountTypes';
import { VscSignOut } from 'react-icons/vsc';
import useRedirectToLoginPage from '../api/hooks/useRedirectToLoginPage';
import ErrorField from '../components/common/error/ErrorField';
import ErrorInput from '../components/common/error/ErrorInput';
import { TfiCheck, TfiClose, TfiPencil, TfiSave, TfiTrash } from 'react-icons/tfi';
import { InputType, MediaInfoEditModel } from '../components/common/edit/MediaInfoTypes';
import DateEditComponent from '../components/common/edit/DateEditComponent';
import { DateToString, GetDate } from '../common/Helper';
import { GetLanguageList } from '../api/LanguageApi';
import { languageQueryKey } from '../components/library/edit/language/LanguageListEditComponent';

const sessionsQueryKey = 'sessions';

export default function UserDetailPage() {
	const { getUser, forceReloadUser } = useUser();
	const queryClient = useQueryClient();
	const { data: user } = useQuery(userQueryKey, getUser);

	const [isEditing, setIsEditingValue] = useState<Array<string>>([]);
	const setEditing = (elementName: string, value: boolean) => {
		const alreadyEditing = isEditing.find(q => q == elementName) != null;
		if (value){
			if (!alreadyEditing){
				setIsEditingValue(isEditing.concat([elementName]))
			}
		}
		else{
			if (alreadyEditing){
				setIsEditingValue(isEditing.filter(q => q != elementName))
			}
		}
	}

	const [firstName, setFirstName] = useState<string | null>(null);
	const [patronymic, setPatronymic] = useState<string | null>(null);
	const [lastName, setLastName] = useState<string | null>(null);
	const [setUserInfoError, setSetUserInfoError] = useState<string | null>(null);
	const toggleIsUserInfoEditing = () => {
		const isUserInfoEditing = isEditing.find(q => q == 'userInformation') != null;
		if (isUserInfoEditing){
			setFirstName(user?.firstName ?? null);
			setPatronymic(user?.patronymic ?? null);
			setLastName(user?.lastName ?? null);
		}
		setEditing('userInformation', !isUserInfoEditing);
	};

	// const { data: languages, isLoading, isError, error } = useQuery(languageQueryKey, GetLanguageList);
	const { data: languages, isError: languagesLoadingError} = useQuery(languageQueryKey, GetLanguageList);
	const [editLanguageError, setEditLanguageError] = useState<string | null>(null);
	const [languageSelected, setLanguageSelected] = useState<string | null>(null);
	const [isLanguageDeleting, setIsLanguageDeleting] = useState<boolean>(false);
	const selectLanguage = (id?: string | null) => setLanguageSelected(id ?? null);
	const [activeSession, setActiveSession] = useState<SessionModel | null>(null);
	const edit = false;
	
	
	const [isAvatarDeleting, setIsAvatarDeleting] = useState<boolean>(false);
	const setAvatar = () =>{
		const config = {  } as AxiosRequestConfig;
		userClient.post({} as MediaInfoEdit, );
	};

	const { toLoginPage } = useRedirectToLoginPage();
	
	const getSessions = () => {
		return new Promise<Array<SessionModel>>((resolve, reject) => {
			GetSessions(user?.accessToken).then((data) => data != undefined ? resolve(data) : reject())
			.catch(() => reject());
		})
	}

	const { data: sessions } = useQuery<Array<SessionModel>>(sessionsQueryKey, getSessions);
	
	useEffect(() => {
		if (user == null){
			setActiveSession(null)	
		}
		else{
			setActiveSession(sessions?.find((q) => q.id == user?.sessionId) ?? null)
		}
		setFirstName(user?.firstName ?? null);
		setPatronymic(user?.patronymic ?? null);
		setLastName(user?.lastName ?? null);
		selectLanguage(user?.languageId ?? null);
	}, [sessions, user, setActiveSession])

	const deleteSession = (sessionId: string) => {
		DeleteSession(user?.accessToken, { sessionId:sessionId } as DeleteSessionModel)
		.then(() => InvalidateSessions(queryClient));
	}

	if (user == null || activeSession == null){
		return (<h1>Писюн</h1>)
	}
	return (
		<div className='row'>
			<div className='col-3'>
				<>
					{!edit &&
						<MediaInfoEditComponent 
							mediaInfo={{
								type: MediaInfoType.Image,
								url: user.avatarData?.url,
								data: null,
								isNew: true,
							} as MediaInfoEditModel}
							inputTypeFilter={InputType.File}
							classes={'card-img-top rounded-3 border border-5 border-secondary'}
							
							isEditing={isEditing.find(q => q == 'avatar') != null}
							setEditing={(_, value) => setEditing('avatar', value)}
							editMediaInfo={(mediaInfo, newUrl, newFile) =>{
								if (newFile == null){
									return Promise.reject('File is null');
								}
								
								return new Promise<string | undefined>((resolve, reject) => {
									SetAvatar(user.accessToken, newFile)
									.then(() => resolve(''))
									.catch((error: Error | undefined) => reject(error?.message ?? null));
								});
							}}
							
							isDeleting={isAvatarDeleting}
							setDeleting={(_, value) => setIsAvatarDeleting(value)}
							
							deleteMediaInfo={() => {
								return new Promise<string | undefined>((resolve, reject) =>{
									DeleteAvatar(user.accessToken)
									.then(() => resolve(''))
									.catch((error: Error | undefined) => reject(error?.message ?? null));
								});
							}}
							dataLoadingError={null}
							forceRefresh={() => forceReloadUser().finally(() => InvalidateUser(queryClient))}
							/>
					}
					{/* {!edit &&
						<MediaInfoComponent
						classes={'card-img-top rounded-3 border border-5 border-secondary'}
						// height='25rem'
						mediaInfo={user.avatarData?.url == null ? null : {
							type: user.avatarData.type,
							data: user.avatarData.url,
						} as MediaInfoModel}
						/>
					} */}
				</>
			</div>
			<div className='col'>
				<h1 className='text-primary'>{user.nickName}</h1>
				<div className='card p-0 mb-2'>
					<div className='card-header'>
						<div className='row justify-content-between'>
							<div className='col'>
								<h3 className='card-title my-0'>Личные данные</h3>
							</div>
							<div className='col-auto'>
								{isEditing.find(q => q == 'userInformation') == null &&
									<div className='btn btn-primary' onClick={toggleIsUserInfoEditing}>
										<TfiPencil />
									</div>
								}
								{isEditing.find(q => q == 'userInformation') != null &&
									<div className='row'>
										<div className='col px-0'>
											<div className={'btn btn-success w-100'} onClick={() => {
												SetUserInformation(user.accessToken, {
													firstName: firstName,
													patronymic: patronymic,
													lastName: lastName,
												} as UserInformationEditModel)
												.then(() => {
													setEditing('userInformation', false);
													setSetUserInfoError(null);
													forceReloadUser().finally(() => InvalidateUser(queryClient));
												})
												.catch((error : Error | undefined) => setSetUserInfoError(error?.message ?? null))
											}}>
												<TfiSave />
											</div>
										</div>
										<div className='col'>
											<div className='btn btn-secondary' onClick={toggleIsUserInfoEditing}>
												<TfiClose />
											</div>
										</div>
									</div>
								}
							</div>
						</div>
					</div>
					<div className='card-body'>
						<div className='row mb-2'>
							<div className='col-2 align-self-center'>Имя</div>
							<div className='col-4'>
								<ErrorField error={setUserInfoError}>
									<ErrorInput error={setUserInfoError}>
										<div className="input-group input-group-sm">
											<ErrorInput error={setUserInfoError}>
												<input className="form-control" type="text" placeholder="Имя" value={firstName ?? ''} disabled={isEditing.find(q => q == 'userInformation') == null} autoComplete='off'
													onChange={(event : ChangeEvent<HTMLInputElement>) => setFirstName(event.target.value)} />
											</ErrorInput>

											{/* { ShowButtons(props, genreProportionPercentage, editGenreProportionError == undefined ? null : editGenreProportionError, SetEditGenreProportionError) } */}

										</div>
									</ErrorInput>
								</ErrorField>
							</div>
						</div>
						<div className='row mb-2'>
							<div className='col-2 align-self-center'>Фамилия</div>
							<div className='col-4'>
								<ErrorField error={setUserInfoError}>
									<ErrorInput error={setUserInfoError}>
										<div className="input-group input-group-sm">
											<ErrorInput error={setUserInfoError}>
												<input className="form-control" type="text" placeholder="Фамилия" value={lastName ?? ''} disabled={isEditing.find(q => q == 'userInformation') == null} autoComplete='off'
													onChange={(event : ChangeEvent<HTMLInputElement>) => setLastName(event.target.value)} />
											</ErrorInput>

											{/* { ShowButtons(props, genreProportionPercentage, editGenreProportionError == undefined ? null : editGenreProportionError, SetEditGenreProportionError) } */}

										</div>
									</ErrorInput>
								</ErrorField>
							</div>
						</div>
						<div className='row mb-2'>
							<div className='col-2 align-self-center'>Отчество</div>
							<div className='col-4'>
								<ErrorField error={setUserInfoError}>
									<ErrorInput error={setUserInfoError}>
										<div className="input-group input-group-sm">
											<ErrorInput error={setUserInfoError}>
												<input className="form-control" type="text" placeholder="Отчество" value={patronymic ?? ''} disabled={isEditing.find(q => q == 'userInformation') == null} autoComplete='off'
													onChange={(event : ChangeEvent<HTMLInputElement>) => setPatronymic(event.target.value)} />
											</ErrorInput>

											{/* { ShowButtons(props, genreProportionPercentage, editGenreProportionError == undefined ? null : editGenreProportionError, SetEditGenreProportionError) } */}

										</div>
									</ErrorInput>
								</ErrorField>
							</div>
						</div>
						<div className='row mb-2'>
							<div className='col-2 align-self-center'>Дата рождения</div>
							<div className='col-4'>
								<DateEditComponent
									placeholder={'Дата рождения'}
									required={true}
									isEditing={isEditing.find(q => q == 'birthDate') != null}
									enabled={true}
									date={GetDate(user?.birthDate)}
									editDate={(value: Date | null) => 
										user == null ? Promise.reject('Пользователь не загружен') : SetBirthDate(user.accessToken, {
											birthDate: value != null ? DateToString(value) : null,
										} as BirthDateEditModel)}
									setEditing={(value: boolean) => setEditing('birthDate', value)}
									dataLoadingError={null}
									forceRefresh={() => forceReloadUser().finally(() => InvalidateUser(queryClient))}
									/>
							</div>
						</div>

						<div className='row'>
							<div className='col-2 align-self-center'>Язык</div>
							<div className='col-4'>
								<ErrorField error={editLanguageError}>
									<ErrorInput error={editLanguageError}>
										<div className="input-group">
											
											<ErrorInput error={editLanguageError}>
												<>
													{isEditing.find(q => q == 'language') == null &&
														<span className='form-control bg-light-subtle w-auto'>
															{
																(languages?.map(q => { return {id:q.id, value:`${q.name} [${q.codeIso3}]`} })
																	.find(q => q.id == languageSelected)?.value ?? 'Язык не выбран')
															}
														</span>
													}
													{isEditing.find(q => q == 'language') != null &&
														<select className="form-select" aria-label="Язык названия" onChange={(event) => selectLanguage(event.target.value)}
															disabled={isEditing.find(q => q == 'language') == null}
															value={languageSelected ?? '---'}
															>
															<option value={''} >Выберите язык названия</option>
															{(languages != undefined &&  languages.length > 0) && ////WRONG!!!!
																React.Children.toArray(
																	languages.map((language) => 
																		<option value={language.id}>
																			{language.name} [{language.codeIso3}]
																		</option>
																	))
															}
														</select>
													}
												</>
											</ErrorInput>

											{(isEditing.find(q => q == 'language') != null && !isLanguageDeleting) &&
												<>
													<ErrorInput error={editLanguageError} errorClassses={'btn-outline-danger'}>
														{/* <button id={GetElementId('btn_edit_language_submit', props.name.id)} type="button" className='btn btn-success' disabled={isError} */}
														<button type="button" className='btn btn-success' disabled={languagesLoadingError}
															onClick={() => 
																	{
																		if (languageSelected != null && languages?.find(q => q.id == languageSelected) == null) return;
																		if (languageSelected != user.languageId){
																			SetLanguage(user.accessToken, { languageId: languageSelected } as LanguageEditModel)
																			.then(() => {
																				setEditLanguageError(null);
																				setEditing('language', false);
																				forceReloadUser().finally(() =>  InvalidateUser(queryClient));
																			})
																			// .catch((error: unknown) => setEditLanguageError((error as Error)?.message));
																			.catch((error : Error | undefined) => {
																				setEditLanguageError(error?.message ?? null);
																			})
																		}
																		else{
																			setEditLanguageError(null);
																			setEditing('language', false);
																		}
																	}
																}>
															<span><TfiCheck /></span>
														</button>
													</ErrorInput>

													<ErrorInput error={editLanguageError} errorClassses={'btn-outline-danger'}>
														{/* <button id={GetElementId('btn_edit_genre_reject', props.genre.id)} type="button" className='btn btn-primary' */}
														<button type="button" className='btn btn-primary'
															onClick={() => {
																// console.log(`props.setEdited(${props.genre.id}, false)`)
																setEditLanguageError(null);
																setEditing('language', false);
															}}>
															<span><TfiClose /></span>
														</button>
													</ErrorInput>
												</>
											}
											{(isLanguageDeleting && isEditing.find(q => q == 'language') == null) &&
												<>
													<ErrorInput error={editLanguageError} errorClassses={'btn-outline-danger'}>
														{/* <button id={GetElementId('btn_edit_genre_submit', props.genre.id)} type="button" className='btn btn-danger' */}
														<button type="button" className='btn btn-danger'
															onClick={() => 
																{
																	SetLanguage(user.accessToken, { languageId: null } as LanguageEditModel)
																		.then(() => {
																			// console.log(`props.setEdited(${props.genre.id}, false)`)
																			setIsLanguageDeleting(false);
																			forceReloadUser().finally(() => InvalidateUser(queryClient));
																		});
																}
															}>
																<span><TfiTrash /></span>
														</button>
													</ErrorInput>

													<ErrorInput error={editLanguageError} errorClassses={'btn-outline-danger'}>
														{/* <button id={GetElementId('btn_edit_genre_reject', props.genre.id)} type="button" className='btn btn-primary' */}
														<button type="button" className='btn btn-primary'
															onClick={() => setIsLanguageDeleting(false)}>
																<span><TfiClose /></span>
														</button>
													</ErrorInput>
												</>
											}
											{(isEditing.find(q => q == 'language') == null && !isLanguageDeleting) &&
												<>

													<ErrorInput error={editLanguageError} errorClassses={'btn-outline-danger'}>
														{/* <button id={GetElementId('btn_switch_to_genre_edit_mode', props.genre.id)} type="button" className='btn btn-primary' disabled={!props.enabled} */}
														{/* <button type="button" className='btn btn-primary' disabled={!props.enabled} */}
														<button type="button" className='btn btn-primary'
															onClick={() => setEditing('language', true)}>
																<span><TfiPencil /></span>
														</button>
													</ErrorInput>

													<ErrorInput error={editLanguageError} errorClassses={'btn-outline-danger'}>
														{/* <button id={GetElementId('btn_switch_to_genre_delete_mode', props.genre.id)} type="button" className='btn btn-danger' disabled={!props.enabled} */}
														{/* <button type="button" className='btn btn-danger' disabled={!props.enabled} */}
														<button type="button" className='btn btn-danger'
															onClick={() => setIsLanguageDeleting(true)}>
																<span><TfiTrash /></span>
														</button>
													</ErrorInput>
												</>
											}

										</div>
										{/* <div className="input-group">
											<ErrorInput error={editGenreError}>
											<input className="form-control" type="text" required={true} placeholder="Жанр" onChange={OnGenreNameChange} value={inputValue} readOnly={!props.isEditing} disabled={!props.enabled}/>
											</ErrorInput>

											{ ShowItem(props, inputValue, editGenreError == undefined ? null : editGenreError, SetEditGenreError) }
										</div> */}
									</ErrorInput>
								</ErrorField>
							</div>
						</div>

					</div>
				</div>

				<div className='row justify-content-between'>
					<div className='col'>
						<h3>Сессии</h3>
					</div>
					<div className='col-auto'>
						<div className='btn btn-sm btn-danger' onClick={() => DeleteAllSessions(user.accessToken).then(() => toLoginPage())}>Выйти на всех устройствах</div>
					</div>
				</div>
				{ShowSession(activeSession, true, deleteSession) }
				<br />
				{sessions != null &&
					React.Children.toArray(
						sessions.filter(q => q.id != activeSession.id).map((session: SessionModel) => ShowSession(session, false, deleteSession))
					)
				}
			</div>
		{/* {//media content} */}
		</div>
	)
}


// function ShowLanguage(languages: Array<Language>, selectedLanguageId: string | null){
// 	const language = (languages ?? []).find(q => q.id == selectedLanguageId);
// 	if (language == null){
// 		return <span> Язык не выбран </span>
// 	}
// }

function ShowSession(session: SessionModel, current: boolean, logoutFunction: (sessionId: string) => void){
	return(
		<div className='card p-0 mb-2'>
			{!current &&
				<div className='card-header row justify-content-end m-0 p-2'>
					{/* <div className='col'>{session.id}</div> */}
					{/* <div className='col'>{session.id} | <h5 className='card-title'>{session.userAgent}</h5></div> */}
					{/* <div className='col'><h2 className='card-title'>{session.userAgent}</h2></div> */}
					<div className='col-auto p-0'>
						<div className='btn btn-sm btn-danger' onClick={() => logoutFunction(session.id)}><VscSignOut /></div>
					</div>
					
				</div>
			}
			<div className='card-body p-2'>
				<h5 className='card-title'>{session.userAgent}</h5>
				<span className='card-text text-muted'>{session.country}, {session.region}</span>
			</div>
			{GetSessionExpireDays(session, 'card-footer p-2 pb-1')}
			{/* <div className="card-footer">
			</div> */}
		</div>
	);
}

function GetSessionExpireDays(session: SessionModel, classString?: string | null) {
    const expireDays = differenceInDays(new Date(), session.expiredDate);
	let daysString = 'дней';
	if (expireDays == 1){
		daysString = 'день';
	}
	else if (expireDays > 1 && expireDays < 5){
		daysString = 'дня';
	}
	if (expireDays < 7){
		return (
			// <h6>Истекает через: <span className={(classString != null ? (classString + ' ') : '') + (expireDays < 3 ? 'text-danger' : 'text-warning')}>{expireDays} {daysString}</span></h6>
			<div className={classString != null ? classString : ''}>
				<h6>Истекает через: <span className={expireDays < 3 ? 'text-danger' : 'text-warning'}>{expireDays} {daysString}</span></h6>
			</div>
		)
	}
	else{
		// <h6>Истекает через: </h6>
		return(
			<></>
		)
	}

}


function differenceInDays(date1: Date, date2: Date): number {
    const oneDay = 24 * 60 * 60 * 1000; // hours*minutes*seconds*milliseconds
    const diffInTime = new Date(date2).getTime() - new Date(date1).getTime();
    return Math.round(diffInTime / oneDay);
}

function InvalidateSessions(queryClient: QueryClient) { queryClient.invalidateQueries({ queryKey: [sessionsQueryKey] }); }
function InvalidateUser(queryClient: QueryClient) { queryClient.invalidateQueries({ queryKey: [userQueryKey] }); }