import { useState } from "react";
import { connect } from "react-redux";

import {
	Button,
	ErrorToast,
	FieldsBehavior,
	Icon,
	MainWrapper,
	Modal,
	Nav,
	Notification,
	Toast,
	ToggleField,
} from "@ax/components";
import { appActions } from "@ax/containers/App";
import { sitesActions } from "@ax/containers/Sites";
import { RouteLeavingGuard } from "@ax/guards";
import { getNavigationModules } from "@ax/helpers";
import { useModal, useShouldBeSaved, useToast } from "@ax/hooks";
import type { IGriddoTheme, IImage, INavItem, IRootState, ISite } from "@ax/types";

import { config } from "components";

import { timezones } from "./constants";
import NavigationModules from "./NavigationModules";

import * as S from "./style";

const themes = config.schemas.config.themes;

const Globals = (props: IProps): JSX.Element => {
	const { isSaving, currentSiteInfo, saveSettings, setHistoryPush, navItems, currentNavItem } = props;

	const [isNavigationNotificationOpen, setIsNavigationNotificationOpen] = useState(false);
	const [tempTheme, setTempTheme] = useState<string | undefined>();
	const [isNavigationModulesChanged, setIsNavigationModulesChanged] = useState(!!currentSiteInfo.navigationModules);
	const [form, setForm] = useState<ISite>(currentSiteInfo);
	const { isOpen, toggleModal } = useModal();
	const { isOpen: isHiddenOpen, toggleModal: toggleHiddenModal } = useModal();
	const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
	const { isDirty, setIsDirty } = useShouldBeSaved(form);

	const { name, timezone, theme, favicon, smallAvatar, bigAvatar, thumbnail, home, hidden, showSitemapInRobots } = form;

	const navigationModules: Record<string, any[]> = getNavigationModules();
	const hasMultipleNavigationModules = Object.keys(navigationModules).some(
		(key: string) => navigationModules[key].length > 1,
	);

	const setValue = (newValue: Partial<ISite>) => setForm((state: ISite) => ({ ...state, ...newValue }));

	const setNameValue = (value: string) => setValue({ name: value });
	const setTimezoneValue = (value: string) => setValue({ timezone: value });
	const setThemeValue = (value: string) => {
		const selectedTheme = (themes as IGriddoTheme[]).find((t) => t.value === value);
		if (selectedTheme?.elements) {
			setTempTheme(value);
			toggleModal();
		} else {
			setValue({ theme: value });
		}
	};
	const setFaviconValue = (value: IImage) => setValue({ favicon: value.url ? value.url : null });
	const setSmallAvatarValue = (value: IImage) => setValue({ smallAvatar: value.url ? value.url : null });
	const setBigAvatarValue = (value: IImage) => setValue({ bigAvatar: value.url ? value.url : null });
	const setThumbnailValue = (value: IImage) => setValue({ thumbnail: value.url ? value.url : null });
	const setRobotsValue = (value: boolean) => {
		setValue({ showSitemapInRobots: value });
		if (value) {
			toggleToast("Sitemap included in robots.txt");
		}
	};
	const setHiddenValue = () => {
		setValue({ hidden: false });
		saveForm({ ...form, hidden: false });
		toggleHiddenModal();
	};
	const setNavigationModulesValue = (value: any) => setValue({ navigationModules: value });

	const handleChangeTheme = () => {
		tempTheme && setValue({ theme: tempTheme });
		toggleModal();
	};

	const saveForm = async (newForm: ISite) => {
		const isSaved = await saveSettings(newForm);
		const isNavigationModulesChanging =
			JSON.stringify(form.navigationModules) !== JSON.stringify(currentSiteInfo.navigationModules);
		setIsNavigationNotificationOpen(isNavigationModulesChanging);
		if (isSaved) setIsDirty(false);
	};

	const handleOpenUrl = () => {
		const win = window.open(home, "_blank");
		if (win) {
			win.focus();
		}
	};

	const rightButtonProps = {
		label: isSaving ? "Saving" : isDirty ? "Save" : "Saved",
		disabled: isSaving || !isDirty,
		action: () => saveForm(form),
	};

	const setRoute = (path: string) => setHistoryPush(path);

	const modalText = (
		<>
			Some settings <strong>are not saved</strong>.
		</>
	);

	const closeNavigationNotification = () => setIsNavigationNotificationOpen(false);
	const goToNavigationModules = () => setHistoryPush("/sites/navigations/modules");
	const goToLanguages = () => setHistoryPush("/sites/settings/languages");

	const mainThemeAction = { title: "Understood", onClick: handleChangeTheme };
	const secondaryThemeAction = { title: "Cancel", onClick: toggleModal };

	const mainHiddenAction = { title: "Enable Indexing", onClick: setHiddenValue };
	const secondaryHiddenAction = { title: "Cancel", onClick: toggleHiddenModal };

	return (
		<>
			<RouteLeavingGuard when={isDirty} action={setRoute} text={modalText} />
			<MainWrapper backLink={false} title="General settings" rightButton={rightButtonProps} showTagHidden={hidden}>
				<S.Wrapper>
					<Nav current={currentNavItem} items={navItems} onClick={setRoute} />
					<S.ContentWrapper>
						<ErrorToast />
						{isNavigationNotificationOpen && (
							<Notification
								type="warning"
								text="The design of the navigation modules has changed. Please, check the previously created."
								btnText="Go to check"
								onClick={goToNavigationModules}
								resetError={closeNavigationNotification}
							/>
						)}
						<S.FormWrapper>
							{hidden ? (
								<S.HiddenFieldWrapper>
									<S.IconWrapper>
										<Icon name="working" size="16" />
									</S.IconWrapper>
									<div>
										Site <strong>hidden from search engines and AI models</strong>. Enable indexing to make it public.
										Permanent action.
									</div>
									<S.StyledToggleField name="hidden" value={!hidden} onChange={toggleHiddenModal} size="s" />
								</S.HiddenFieldWrapper>
							) : (
								<S.HiddenFieldWrapper>
									<S.IconWrapper>
										<Icon name="party" size="16" />
									</S.IconWrapper>
									<div>
										This site is currently <strong>visible to search engines and AI models</strong>. This is permanent
										and cannot be changed.
									</div>
								</S.HiddenFieldWrapper>
							)}
							<FieldsBehavior
								title="Site Name"
								name="name"
								fieldType="TextField"
								value={name || ""}
								onChange={setNameValue}
							/>
							<FieldsBehavior
								title="Domain default language"
								name="domain"
								fieldType="TextField"
								readonly={true}
								value={home || ""}
								helptext="To make the changes, go to Language's settings."
								icon="openOutside"
								onClickIcon={handleOpenUrl}
							/>
							<S.ButtonWrapper>
								<Button type="button" buttonStyle="line" onClick={goToLanguages}>
									Go to languages
								</Button>
							</S.ButtonWrapper>
							<FieldsBehavior
								title="Timezone"
								name="timezone"
								fieldType="Select"
								value={timezone}
								options={timezones}
								onChange={setTimezoneValue}
								mandatory={true}
							/>
							<FieldsBehavior
								title="Site theme"
								name="theme"
								fieldType="Select"
								value={theme}
								options={themes}
								onChange={setThemeValue}
								mandatory={true}
							/>
							{hasMultipleNavigationModules && (
								<NavigationModules
									navigationModules={navigationModules}
									form={form}
									setNavigationModulesValue={setNavigationModulesValue}
									isNavigationModulesChanged={isNavigationModulesChanged}
									setIsNavigationModulesChanged={setIsNavigationModulesChanged}
									theme={theme ?? ""}
								/>
							)}
							<S.SectionWrapper>
								<S.Heading>Include sitemap in Robots.txt</S.Heading>
								<S.RobotsWrapper>
									<S.Description>
										By selecting this option, the <strong>sitemap of this site will be published in robots.txt</strong>,
										making it easier for search engines to find your pages and therefore improving your SEO ranking.
									</S.Description>
									<ToggleField name="robots" value={showSitemapInRobots} onChange={setRobotsValue} size="s" />
								</S.RobotsWrapper>
							</S.SectionWrapper>
							<S.SectionWrapper>
								<S.Heading>Site Identity</S.Heading>
								<S.Description>Manage how this site appears on the dashboard and browser tabs.</S.Description>
								<S.ColumnsWrapper>
									<FieldsBehavior
										title="Favicon"
										name="favicon"
										value={favicon || null}
										fieldType="ImageField"
										onChange={setFaviconValue}
										helptext="Small icon shown in browser tabs. Upload a png, svg, jpg image"
										selectPosition={false}
										fullWidth={true}
										previewHeight={212}
										previewWidth={348}
										objectFit="contain"
										noGallery
									/>
									<FieldsBehavior
										title="Dashboard Thumbnail"
										name="thumbnail"
										value={thumbnail || null}
										fieldType="ImageField"
										onChange={setThumbnailValue}
										helptext="Used on the sites dashboard. Upload a png, svg, jpg image"
										selectPosition={false}
										fullWidth={true}
										previewHeight={212}
										previewWidth={348}
										noGallery
									/>
								</S.ColumnsWrapper>
							</S.SectionWrapper>
							<S.SectionWrapper>
								<S.Heading>Navigation Branding</S.Heading>
								<S.Description>Upload the logos displayed in the main navigation menu.</S.Description>
								<S.ColumnsWrapper>
									<FieldsBehavior
										title="Collapsed Griddo menu logo"
										name="smallAvatar"
										value={smallAvatar || null}
										fieldType="ImageField"
										onChange={setSmallAvatarValue}
										helptext="When collapsed, it appears in the Griddo menu. Recommended min size: 32x32px."
										selectPosition={false}
										fullWidth={true}
										previewHeight={212}
										previewWidth={348}
										objectFit="contain"
										noGallery
									/>
									<FieldsBehavior
										title="Expanded Griddo menu logo"
										name="bigAvatar"
										value={bigAvatar || null}
										fieldType="ImageField"
										onChange={setBigAvatarValue}
										helptext="When expanded, it appears in the Griddo menu. Recommended min size: 208x32px."
										selectPosition={false}
										fullWidth={true}
										previewHeight={212}
										previewWidth={348}
										objectFit="contain"
										noGallery
									/>
								</S.ColumnsWrapper>
							</S.SectionWrapper>
						</S.FormWrapper>
					</S.ContentWrapper>
				</S.Wrapper>
				{isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
				<Modal
					isOpen={isOpen}
					hide={toggleModal}
					title="Theme Change Warning"
					secondaryAction={secondaryThemeAction}
					mainAction={mainThemeAction}
					size="S"
				>
					<S.ModalContent>
						<p>
							The selected theme has some restrictions. By switching to this theme,
							<strong>you may lose access to some modules or templates.</strong>
						</p>
					</S.ModalContent>
				</Modal>
				<Modal
					isOpen={isHiddenOpen}
					hide={toggleHiddenModal}
					title="Enable public indexing?"
					secondaryAction={secondaryHiddenAction}
					mainAction={mainHiddenAction}
					size="S"
					height={240}
				>
					<S.ModalContent>
						<p>
							You are about to <strong>make this site visible to search engines</strong>. This will also{" "}
							<strong>update the llms.txt</strong> file to allow AI models to access and read your content. This action
							is permanent and cannot be undone.
						</p>
					</S.ModalContent>
				</Modal>
			</MainWrapper>
		</>
	);
};

interface IProps {
	isSaving: boolean;
	currentSiteInfo: ISite;
	navItems: INavItem[];
	currentNavItem: INavItem;
	saveSettings(form: ISite): Promise<boolean>;
	setHistoryPush(path: string, isEditor?: boolean): void;
}

const mapDispatchToProps = {
	setHistoryPush: appActions.setHistoryPush,
	saveSettings: sitesActions.saveSettings,
};

const mapStateToProps = (state: IRootState) => ({
	isSaving: state.app.isSaving,
	currentSiteInfo: state.sites.currentSiteInfo!,
});

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