import { AnimatePresence, motion } from "framer-motion";
import type { ReactElement } from "react";
import Lottie from "react-lottie";

import animationData from "@assets/lottie/coin-stack.json";
import postFlightAnimationData from "@assets/lottie/post-flight.json";

import { BrokenConnection, VerifiedCheck } from "@components/common/Icons";
import { TokenDisplay } from "@components/common/TokenDisplay";
import { TokenIcon } from "@components/common/TokenIcon";
import type { STATUS_CODE, StatusEndPoint } from "@hooks/apis/useRequestStatus";
import { useMappedChainData } from "@hooks/useMappedChainData";
import type { Token } from "@providers/ConfigProvider";
import { getOrderStatus } from "@utils/getOrderStatus";

const AnimatedWrapper = ({ children }: { children: ReactElement }) => {
	return (
		<AnimatePresence>
			<motion.div
				initial={{ opacity: 0, y: -10 }}
				animate={{ opacity: 1, y: 0 }}
				exit={{ opacity: 0 }}
				transition={{ ease: "easeInOut", duration: 0.5 }}
			>
				{children}
			</motion.div>
		</AnimatePresence>
	);
};

const animationOptions = {
	loop: false,
	autoplay: true,
	animationData: animationData,
	renderSettings: {
		preserveAspectRatio: "xMidyMid slice",
	},
};

const postFlightAnimationOptions = {
	loop: false,
	autoplay: true,
	animationData: postFlightAnimationData,
	renderSettings: {
		preserveAspectRatio: "xMidyMid slide",
	},
};

export const Header = ({
	statusCode,
	input,
	output,
	isSurplusAmountReceived = false,
}: {
	statusCode: STATUS_CODE;
	input: StatusEndPoint[];
	output: StatusEndPoint[];
	isSurplusAmountReceived?: boolean;
}) => {
	const { isCompleted, isPending, inProgress, isExpired } =
		getOrderStatus(statusCode);
	const inputToken = input[0].token;
	const outputToken = output[0].token;

	function renderCompletedIllustration() {
		if (isSurplusAmountReceived) {
			return (
				<div className="bn-size-[120px] overflow-hidden">
					<Lottie options={animationOptions} width={130} height={130} />
				</div>
			);
		}

		return (
			<div>
				<Lottie options={postFlightAnimationOptions} width={110} height={110} />
			</div>
		);
	}

	return (
		<AnimatePresence mode="wait">
			{isPending && (
				<AnimatedWrapper key="pending">
					<TokenSearchCreative token={inputToken} />
				</AnimatedWrapper>
			)}

			{inProgress && (
				<AnimatedWrapper key="in-progress">
					<TokenDisplay input={input} output={output} />
				</AnimatedWrapper>
			)}

			{isCompleted && (
				<AnimatedWrapper key="completed">
					{renderCompletedIllustration()}
				</AnimatedWrapper>
			)}

			{isExpired && (
				<AnimatedWrapper key="expired">
					<RequestExpired />
				</AnimatedWrapper>
			)}
		</AnimatePresence>
	);
};

const TokenSearchCreative = ({ token }: { token: Token }) => {
	const mappedChainData = useMappedChainData();
	const networkUrl = mappedChainData?.[token?.chainId]?.icon ?? "";

	return (
		<div className="bn-relative bn-size-[66px] bn-border-4 bn-border-solid bn-border-primary bn-rounded-full bn-flex bn-items-center bn-justify-center">
			<div className="bn-size-10 bn-rounded-full bn-relative">
				<TokenIcon classNames="bn-w-full bn-h-full" url={token.logoURI} />
				<TokenIcon
					classNames="bn-absolute -bn-bottom-0.5 -bn-right-0.5 bn-size-5"
					url={networkUrl}
				/>
			</div>
			{/* ping animation */}
			<div className="bn-animate-ping bn-absolute bn-top-0 bn-left-0 bn-size-full bn-rounded-full bn-border-2 bn-border-solid bn-border-primary" />
		</div>
	);
};

const TokenSuccessCreative = ({ url }: { url: string }) => {
	return (
		<div className="bn-size-[70px] bn-rounded-full bn-relative bn-bg-layer-2 bn-flex bn-items-center bn-justify-center bn-border-2 bn-border-solid bn-border-primary">
			<TokenIcon url={url} classNames="bn-size-[54px]" />
			<VerifiedCheck className="bn-absolute bn-bottom-1 -bn-right-1.5" />
		</div>
	);
};

const RequestExpired = () => {
	return <BrokenConnection />;
};
