import { useEffect, useState } from "react";

import type { IShareData } from "@ax/api";
import { shareToken as shareTokenApi } from "@ax/api";
import { Button, Loader, StatusTile, TextField } from "@ax/components";
import { copyTextToClipboard, DEV_NOW, formatDate, getShareTokenInfo, isReqOk } from "@ax/helpers";
import { useToast } from "@ax/hooks";

import Modal from "../Modal";
import Toast from "../Toast";

import * as S from "./style";

const SharePageModal = (props: SharePageModalProps): JSX.Element | null => {
	const { isOpen, hide, pageID, entity, pageTitle, shareData, onShareChange } = props;

	const { isVisible, toggleToast, setIsVisible, state: toastState } = useToast();
	const [showActions, setShowActions] = useState(false);
	const [loading, setLoading] = useState(false);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		if (isOpen && !shareData && !loading) {
			handleCreateShare();
		}
	}, [isOpen, shareData]);

	if (!isOpen) return null;

	const tokenInfo = shareData ? getShareTokenInfo(shareData, DEV_NOW) : null;
	const shareUrl = shareData ? `${window.location.origin}/page-preview/${pageID}/${entity}` : "";

	const renewalPreview =
		shareData && showActions && tokenInfo
			? (() => {
					const currentExpiration = new Date(shareData.endDate);
					const renewalDate = new Date(currentExpiration);
					renewalDate.setDate(renewalDate.getDate() + shareData.daysValid);
					return {
						date: formatDate(renewalDate),
						days: tokenInfo.validTokenDaysUntilExpires + shareData.daysValid,
					};
				})()
			: null;

	const handleCopy = () => {
		copyTextToClipboard(shareUrl).then(
			() => toggleToast("URL Copied"),
			(err) => console.error("Could not copy text: ", err),
		);
	};

	const handleCreateShare = async () => {
		setLoading(true);
		const response = await shareTokenApi.createShare(pageID);
		if (isReqOk(response.status)) {
			onShareChange(response.data);
		}
		setShowActions(false);
		setLoading(false);
	};

	const handleRenew = async () => {
		setLoading(true);
		const response = await shareTokenApi.renewShare(pageID);
		if (isReqOk(response.status)) {
			onShareChange(response.data);
		}
		setShowActions(false);
		setLoading(false);
	};

	const handleHide = () => {
		setShowActions(false);
		hide();
	};

	const getModalActions = () => {
		if (tokenInfo?.tokenHasExpired) {
			return {
				main: { title: "generate new link", onClick: handleCreateShare, disabled: loading, icon: "refresh" },
				secondary: { title: "cancel", onClick: handleHide },
			};
		}
		if (showActions) {
			return {
				main: { title: "renew link", onClick: handleRenew, disabled: loading, icon: "refresh" },
				secondary: {
					title: "cancel",
					onClick: () => handleHide(),
				},
			};
		}
		return { main: undefined, secondary: undefined };
	};

	const { main: mainAction, secondary: secondaryAction } = getModalActions();

	return (
		<>
			<Modal
				isOpen={isOpen}
				hide={handleHide}
				size="S"
				height="auto"
				title="Share Draft"
				mainAction={mainAction}
				secondaryAction={secondaryAction}
			>
				<S.ModalContent>
					<S.Description>
						Generate a secure, time-limited link to share the draft <strong>{pageTitle}</strong> with external
						reviewers. They won't need a Griddo account to view it.
					</S.Description>

					{loading && (
						<S.LoaderWrapper>
							<Loader name="circle" size="60px" />
						</S.LoaderWrapper>
					)}

					{!loading && shareData && tokenInfo && (
						<>
							<S.PreviewLinkWrapper expired={tokenInfo.tokenHasExpired}>
								<S.Label>Secure preview link</S.Label>
								<TextField
									value={shareUrl}
									icon="copy"
									onChange={() => {}}
									onClickIcon={handleCopy}
									noeditable
									selectOnFocus
									disabled={tokenInfo.tokenHasExpired}
								/>
							</S.PreviewLinkWrapper>
							<S.StatusLineWrapper>
								{tokenInfo.tokenHasExpired ? (
									<StatusTile
										icon="user"
										title="Expired"
										description={`${tokenInfo.validTokenDaysUntilExpires} days`}
										detail={`Expired on ${tokenInfo.tokenExpirationDate}`}
										mode="warning"
									/>
								) : tokenInfo.tokenExpiringSoon ? (
									<StatusTile
										icon="user"
										title={renewalPreview ? "Valid" : "Expiring soon"}
										description={`${renewalPreview ? renewalPreview.days : tokenInfo.validTokenDaysUntilExpires} days`}
										detail={`Expires ${renewalPreview ? renewalPreview.date : tokenInfo.tokenExpirationDate}`}
										mode={renewalPreview ? "info" : "warning"}
									/>
								) : (
									<StatusTile
										icon="user"
										title="Valid"
										description={`${renewalPreview ? renewalPreview.days : tokenInfo.validTokenDaysUntilExpires} days`}
										detail={`Expires ${renewalPreview ? renewalPreview.date : tokenInfo.tokenExpirationDate}`}
										mode="info"
									/>
								)}

								<StatusTile
									icon="scheduled"
									title="Activity"
									description={`${shareData.visitCount} views`}
									detail={`Shared since ${formatDate(new Date(shareData.startDate))}`}
									mode="info"
								/>
							</S.StatusLineWrapper>
						</>
					)}
					{!showActions && tokenInfo?.tokenCanBeRenewed && shareData && (
						<S.RenewTextButton>
							<Button type="button" buttonStyle="text" icon="refresh" onClick={() => setShowActions(true)}>
								{`renew for ${shareData.daysValid} days`}
							</Button>
						</S.RenewTextButton>
					)}
				</S.ModalContent>
			</Modal>
			{isVisible && <Toast message={toastState} setIsVisible={setIsVisible} />}
		</>
	);
};

interface SharePageModalProps {
	isOpen: boolean;
	hide: () => void;
	pageID: number;
	entity: string;
	pageTitle: string;
	shareData: IShareData | null;
	onShareChange: (shareData: IShareData) => void;
	height?: string;
}

export default SharePageModal;
