import { useState } from "react";
import type { Area } from "react-easy-crop";
import { connect } from "react-redux";

import { Modal } from "@ax/components";
import { appActions } from "@ax/containers/App";
import { galleryActions } from "@ax/containers/Gallery";
import { usersActions } from "@ax/containers/Users";
import { getCroppedImg } from "@ax/helpers";
import type { IImage, IModal, IRole, IRootState, ISite, IUser } from "@ax/types";

import DataStep from "./DataStep";
import FinalStep from "./FinalStep";
import ImageStep from "./ImageStep";
import TimezoneStep from "./TimezoneStep";
import { getCompanyFromEmail } from "./utils";
import WelcomeStep from "./WelcomeStep";

import * as S from "./style";

type Step = "welcome" | "image" | "data" | "timezone" | "final";
const STEPS: Step[] = ["welcome", "image", "data", "timezone", "final"];

const WelcomeModal = (props: IProps) => {
	const { isOpen, toggleModal, currentUser, roles, sites, uploadImage, updateUser, setHistoryPush } = props;

	const [currentStep, setCurrentStep] = useState<Step>("welcome");
	const [croppedImageFile, setCroppedImageFile] = useState<File | null>(null);
	const [isSaving, setIsSaving] = useState(false);
	const [userForm, setUserForm] = useState<IUserFormState>({
		name: currentUser.name,
		username: currentUser.username,
		position: currentUser.position || "",
		company: getCompanyFromEmail(currentUser.email),
		timezone: Intl.DateTimeFormat().resolvedOptions().timeZone ?? "",
	});

	const stepIndex = STEPS.indexOf(currentStep);
	const { isSuperAdmin, roles: userRoles } = currentUser;

	const handleBack = () => setCurrentStep(STEPS[stepIndex - 1]);

	const handleNext = () => setCurrentStep(STEPS[stepIndex + 1]);

	const handleSaveAndFinish = async () => {
		if (!currentUser?.id) return;
		setIsSaving(true);
		try {
			let image: IImage | null = null;
			if (croppedImageFile) {
				image = await uploadImage(croppedImageFile, "global", undefined, false);
			}
			await updateUser(
				currentUser.id,
				{
					...currentUser,
					username: userForm.username,
					company: userForm.company,
					timezone: userForm.timezone,
					position: userForm.position,
					image,
					profileCreated: true,
				},
				true,
				false,
			);
		} catch (e) {
			console.error("Profile update failed", e);
		}
		setIsSaving(false);
		setCurrentStep(STEPS[stepIndex + 1]);
	};

	const handleSkipAndClose = async () => {
		if (!currentUser?.id) return;
		if (currentStep !== "final") {
			await updateUser(currentUser.id, { ...currentUser, profileCreated: true }, true, false);
			setCurrentStep("final");
		} else {
			toggleModal();
		}
	};

	const handleClose = () => {
		setCurrentStep("welcome");
		setCroppedImageFile(null);
		toggleModal();
	};

	const handleViewProfile = () => {
		handleClose();
		setHistoryPush("/profile");
	};

	const handleCropConfirmed = async (imageSrc: string, croppedAreaPixels: Area) => {
		const file = await getCroppedImg(imageSrc, croppedAreaPixels);
		setCroppedImageFile(file);
		setCurrentStep(STEPS[stepIndex + 1]);
	};

	const getTitle = (step: string) => {
		switch (step) {
			case "image":
				return "Step 1 of 3: Profile Picture";
			case "data":
				return "Step 2 of 3: Profile data";
			case "timezone":
				return "Step 3 of 3: Define timezone";
			case "final":
				return "🎉 Ready to start :)";
			default:
				return "Welcome";
		}
	};

	const getBarSize = (step: string) => {
		switch (step) {
			case "image":
				return "33%";
			case "data":
				return "66%";
			case "timezone":
				return "100%";
			default:
				return "0";
		}
	};

	const globalSiteRole = userRoles.find((ur) => ur.siteId === "global");
	const allSiteRole = userRoles.find((ur) => ur.siteId === "all");
	const hasOnlyAllSites = !!allSiteRole && !globalSiteRole;
	const size = currentStep === "final" && !isSuperAdmin && !hasOnlyAllSites ? "XL" : "L";
	const height = currentStep === "final" && !isSuperAdmin && !hasOnlyAllSites ? 608 : 563;

	return (
		<Modal isOpen={isOpen} hide={handleSkipAndClose} title={getTitle(currentStep)} size={size} height={height}>
			<>
				<S.ProgressBar width={getBarSize(currentStep)} />
				{currentStep === "welcome" && <WelcomeStep onSkip={handleSkipAndClose} onClickNext={handleNext} />}
				{currentStep === "image" && (
					<ImageStep onCropConfirmed={handleCropConfirmed} onSkip={handleNext} userImage={currentUser.image?.url} />
				)}
				{currentStep === "data" && (
					<DataStep
						onClickNext={handleNext}
						onClickBack={handleBack}
						form={userForm}
						setForm={setUserForm}
						croppedImageUrl={croppedImageFile ? URL.createObjectURL(croppedImageFile) : null}
					/>
				)}
				{currentStep === "timezone" && (
					<TimezoneStep
						onClickNext={handleSaveAndFinish}
						onClickBack={handleBack}
						form={userForm}
						setForm={setUserForm}
						isSaving={isSaving}
					/>
				)}
				{currentStep === "final" && (
					<FinalStep
						onClose={handleClose}
						onViewProfile={handleViewProfile}
						isSuperAdmin={isSuperAdmin}
						userRoles={userRoles}
						roles={roles}
						sites={sites}
					/>
				)}
			</>
		</Modal>
	);
};

interface IStateProps {
	currentUser: IUser;
	roles: IRole[];
	sites: ISite[];
}

export interface IUserFormState {
	name: string;
	username: string;
	position: string;
	company: string;
	timezone: string;
}

interface IDispatchProps {
	uploadImage: (
		file: File,
		site: number | string,
		setProgress?: (progress: number) => void,
		visible?: boolean,
	) => Promise<IImage | null>;
	updateUser: (id: number, data: IUser, isProfile: boolean, isList?: boolean) => Promise<boolean>;
	setHistoryPush: (path: string) => void;
}

type IProps = IModal & IStateProps & IDispatchProps;

const mapStateToProps = (state: IRootState): IStateProps => ({
	currentUser: state.users.currentUser!,
	roles: state.users.roles,
	sites: state.sites.allSites,
});

const mapDispatchToProps = {
	uploadImage: galleryActions.uploadImage,
	updateUser: usersActions.updateUser,
	setHistoryPush: appActions.setHistoryPush,
};

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