import { useCallback, useEffect, useState } from "react";
import { connect } from "react-redux";

import {
	ErrorToast,
	FieldsBehavior,
	FloatingNote,
	Loading,
	MainWrapper,
	ProfileImage,
	Tabs,
	UserRolesAndSites,
} from "@ax/components";
import { appActions } from "@ax/containers/App";
import { sitesActions } from "@ax/containers/Sites";
import { usersActions } from "@ax/containers/Users";
import { RouteLeavingGuard } from "@ax/guards";
import { useModal, useShouldBeSaved, useURLSearchParam } from "@ax/hooks";
import type { IImage, IRole, IRootState, ISite, IUser } from "@ax/types";

import { timezones } from "../../Settings/Globals/constants";
import { LinkDeviceModal } from "./atoms";

import * as S from "./style";

const PROFILE_TABS = {
	PROFILE: "Profile",
	PERMISSIONS: "Your permissions",
} as const;

const PROFILE_TAB_LIST = [PROFILE_TABS.PROFILE, PROFILE_TABS.PERMISSIONS] as const;

const Profile = (props: IProps) => {
	const { user, updateUser, isSaving, isLoading, getSites, token, roles, sites, setHistoryPush } = props;

	if (!user) {
		throw new Error(`ERROR: User reached Profile with null user`);
	}

	const isUserInit = useURLSearchParam("init");
	const initForm = {
		...user,
		timezone: user.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone ?? "",
	};

	const [form, setForm] = useState<IUser>(initForm);
	const [activeTab, setActiveTab] = useState<(typeof PROFILE_TABS)[keyof typeof PROFILE_TABS]>(PROFILE_TABS.PROFILE);
	const { isOpen, toggleModal } = useModal();
	const { isDirty, setIsDirty } = useShouldBeSaved(form);

	useEffect(() => {
		if (isUserInit) {
			getSites();
		}
	}, [isUserInit, getSites]);

	const { username, name, email, image, company, position, timezone, isSuperAdmin } = form;

	const handleNameChange = useCallback((value: string) => setForm((prev) => ({ ...prev, name: value })), []);
	const handleEmailChange = useCallback((value: string) => setForm((prev) => ({ ...prev, email: value })), []);
	const handleUsernameChange = useCallback((value: string) => setForm((prev) => ({ ...prev, username: value })), []);
	const handleCompanyChange = useCallback((value: string) => setForm((prev) => ({ ...prev, company: value })), []);
	const handlePositionChange = useCallback((value: string) => setForm((prev) => ({ ...prev, position: value })), []);
	const handleTimezoneChange = useCallback((value: string) => setForm((prev) => ({ ...prev, timezone: value })), []);
	const handleImageChange = useCallback((value: IImage) => setForm((prev) => ({ ...prev, image: value })), []);

	const handleSave = async () => {
		const isUpdated = form.id ? await updateUser(form.id, form, true, false) : false;
		if (isUpdated) setIsDirty(false);
	};

	const rightButtonProps = {
		label: isSaving ? "Saving" : isDirty ? "Save profile" : "Saved",
		disabled: isSaving || !isDirty,
		action: handleSave,
	};

	const lineButtonProps = user.isSuperAdmin
		? {
				label: "Link Device",
				action: toggleModal,
				icon: "QrCode",
			}
		: undefined;

	const guardProps = {
		action: (path: string) => setHistoryPush(path),
		text: (
			<>
				Some changes <strong>are not saved</strong>.
			</>
		),
	};

	if (isLoading) return <Loading />;

	return (
		<MainWrapper title="My Profile" rightLineButton={lineButtonProps} rightButton={rightButtonProps}>
			<RouteLeavingGuard when={isDirty} {...guardProps} />
			<ErrorToast size="l" />
			<S.ProfileWrapper>
				<S.Header>
					<S.HeaderContent>
						<S.AvatarWrapper>
							<ProfileImage imageUrl={image?.url} handleImage={handleImageChange} />
						</S.AvatarWrapper>
						<S.UserName>
							<S.SubTitle>USER DATA</S.SubTitle>
							<S.NameTitle>{form.name}</S.NameTitle>
						</S.UserName>
					</S.HeaderContent>
				</S.Header>
				<S.TabsWrapper>
					<Tabs tabs={Array.from(PROFILE_TAB_LIST)} active={activeTab} setSelectedTab={setActiveTab} />
				</S.TabsWrapper>
				<S.Content>
					{activeTab === PROFILE_TABS.PROFILE && (
						<S.UserForm>
							<S.FormColumn>
								<FieldsBehavior
									title="Name"
									name="name"
									fieldType="TextField"
									placeholder="Type a name"
									mandatory
									value={name}
									onChange={handleNameChange}
								/>
								<FieldsBehavior
									title="Alias"
									name="username"
									fieldType="TextField"
									placeholder="Type an alias"
									mandatory
									value={username}
									onChange={handleUsernameChange}
									prefix="@"
								/>
								<FieldsBehavior
									title="Email"
									name="email"
									fieldType="TextField"
									placeholder="Type an email"
									mandatory
									value={email}
									onChange={handleEmailChange}
									disabled={true}
								/>
								<FieldsBehavior
									title="Password"
									name="password"
									fieldType="TextField"
									inputType="password"
									placeholder="Type a password"
									mandatory
									readonly
									value="********"
									icon="edit"
									onClickIcon={toggleModal}
								/>
							</S.FormColumn>
							<S.FormColumn>
								<FieldsBehavior
									title="Job Title"
									name="position"
									fieldType="TextField"
									placeholder="Type your job title"
									value={position || ""}
									onChange={handlePositionChange}
								/>
								<FieldsBehavior
									title="Company"
									name="company"
									fieldType="TextField"
									placeholder="Type a company"
									value={company || ""}
									onChange={handleCompanyChange}
								/>
								<FieldsBehavior
									title="Time zone"
									name="timezone"
									fieldType="Select"
									value={timezone}
									options={timezones}
									onChange={handleTimezoneChange}
									mandatory={true}
									helptext="Used to display time in emails and ensure accurate scheduling."
								/>
							</S.FormColumn>
						</S.UserForm>
					)}
					{activeTab === PROFILE_TABS.PERMISSIONS && (
						<S.UserPermissions>
							<FloatingNote
								icon="info"
								message="This information is not editable. Changes require appropriate permissions and must be made in the user list."
							/>
							<UserRolesAndSites
								isSuperAdmin={isSuperAdmin}
								userRoles={user.roles}
								sites={sites}
								roles={roles}
								showRows={false}
							/>
						</S.UserPermissions>
					)}
				</S.Content>
			</S.ProfileWrapper>
			<LinkDeviceModal isOpen={isOpen} toggleModal={toggleModal} token={token} />
		</MainWrapper>
	);
};

const mapStateToProps = (state: IRootState) => ({
	user: state.users.currentUser!,
	isSaving: state.app.isSaving,
	isLoading: state.app.isLoading,
	token: state.app.token,
	roles: state.users.roles,
	sites: state.sites.allSites,
});

interface IDispatchProps {
	setHistoryPush(path: string): Promise<void>;
	getSites(): Promise<void>;
	updateUser(id: number, data: IUser, isProfile: boolean, isList: boolean): Promise<boolean>;
}

const mapDispatchToProps = {
	setHistoryPush: appActions.setHistoryPush,
	updateUser: usersActions.updateUser,
	getSites: sitesActions.getSites,
};

interface IProfileProps {
	user: IUser | null;
	isSaving: boolean;
	isLoading: boolean;
	token: string;
	roles: IRole[];
	sites: ISite[];
}

type IProps = IProfileProps & IDispatchProps;

export default connect(mapStateToProps, mapDispatchToProps)(Profile);
