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

import { ErrorToast, FieldsBehavior, Modal } from "@ax/components";
import { slugify } from "@ax/helpers";
import type { ILanguage, IModal, IRootState, ISite } from "@ax/types";

import * as S from "./style";

const INITIAL_FORM_STATE: Partial<ISite> = {
	name: "",
	defaultLanguage: null,
	path: "",
	domain: null,
	hidden: true,
	timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};

const REQUIRED_MODAL_FIELDS = ["name", "defaultLanguage", "domain", "path"] as const;

const SiteModal = (props: ISiteModalProps): JSX.Element => {
	const { languages, isOpen, toggleModal, saveSettings, setHistoryPush, isSaving } = props;

	const [form, setForm] = useState(INITIAL_FORM_STATE);
	const { name, defaultLanguage, path, domain } = form;
	const globalDefaultLang = languages?.find((lang: ILanguage) => lang.isDefault);

	const updateForm = useCallback(
		(newValue: Record<string, string | number>) => setForm((state: Partial<ISite>) => ({ ...state, ...newValue })),
		[],
	);

	const setNameValue = useCallback((value: string) => updateForm({ name: value, path: slugify(value) }), [updateForm]);
	const setLangValue = useCallback((value: number) => updateForm({ defaultLanguage: value }), [updateForm]);
	const setPathValue = useCallback((value: string) => updateForm({ path: value }), [updateForm]);
	const setDomainValue = useCallback((value: number) => updateForm({ domain: value }), [updateForm]);

	useEffect(() => {
		if (isOpen && globalDefaultLang) {
			setLangValue(globalDefaultLang.id);
		} else if (!isOpen) {
			setForm(INITIAL_FORM_STATE);
		}
	}, [isOpen, globalDefaultLang, setLangValue]);

	const isFieldValid = (value: any): boolean => {
		return typeof value === "string" ? value.trim().length > 0 : value !== null && value !== undefined;
	};

	const isSubmitDisabled =
		isSaving || !REQUIRED_MODAL_FIELDS.every((field) => isFieldValid(form[field as keyof typeof form]));

	const saveSiteSettings = useCallback(async () => {
		const result = await saveSettings(form);
		if (result) {
			const contentPath = "/sites/settings/globals";
			setHistoryPush(contentPath, false);
			setForm(INITIAL_FORM_STATE);
		}
	}, [form, saveSettings, setHistoryPush]);

	const handleClose = useCallback(() => {
		setForm(INITIAL_FORM_STATE);
		toggleModal();
	}, [toggleModal]);

	const mainAction = {
		title: isSaving ? "Creating..." : "Create site",
		onClick: saveSiteSettings,
		disabled: isSubmitDisabled,
	};
	const secondaryAction = { title: "Cancel", onClick: handleClose };

	return (
		<Modal
			isOpen={isOpen}
			hide={handleClose}
			size="M"
			title="New Site"
			mainAction={mainAction}
			secondaryAction={secondaryAction}
			height="auto"
		>
			<ErrorToast size="l" />
			<S.Form data-testid="site-modal-form">
				<S.FieldsWrapper>
					<FieldsBehavior
						title="Name"
						name="name"
						fieldType="TextField"
						value={name}
						mandatory={true}
						placeholder="Type a name of your new site"
						onChange={setNameValue}
					/>
					<FieldsBehavior
						title="Select default language"
						name="language"
						fieldType="AsyncSelect"
						value={defaultLanguage}
						entity="languages"
						onChange={setLangValue}
						mandatory={true}
					/>
				</S.FieldsWrapper>
				<S.FieldsWrapper>
					<FieldsBehavior
						title="Domain"
						name="domain"
						fieldType="AsyncSelect"
						entity="domains"
						value={domain}
						onChange={setDomainValue}
						mandatory={true}
					/>
					<FieldsBehavior
						title="Path"
						name="path"
						fieldType="TextField"
						value={path}
						mandatory={true}
						placeholder="/site"
						onChange={setPathValue}
						helptext="The path is for the site on this language. Please, fill with the name of the site. Example: /the-site-url"
					/>
				</S.FieldsWrapper>
			</S.Form>
		</Modal>
	);
};

const mapStateToProps = (state: IRootState) => ({
	languages: state.app.globalLangs,
	isSaving: state.app.isSaving,
});

interface IReduxProps {
	languages?: ILanguage[];
	isSaving: boolean;
}

interface IOwnProps extends IModal {
	saveSettings: (form: Partial<ISite>) => Promise<boolean>;
	setHistoryPush: (path: string, isEditor?: boolean) => void;
}

type ISiteModalProps = IReduxProps & IOwnProps;

export default connect(mapStateToProps)(SiteModal);
