import { useState } from "react";
import { type RefinementCtx, z } from "zod/v4";
import { useTranslation } from "~/providers/I18nProvider";

export const zStrongPassword = z.string().superRefine((password, ctx) => {
	const test = [/.{8,}/, /[0-9]/, /[a-z]/, /[A-Z]/].every((regex) =>
		regex.test(password),
	);
	if (!test) {
		ctx.addIssue({
			code: "custom",
			message:
				"La password deve contenere almeno 8 caratteri, un numero, una lettera minuscola e una maiuscola.",
		});
	}
});

type PasswordManager = {
	getStrengthColor: (score: number) => string;
	getStrengthTxt: (score: number) => string;
	isVisible: boolean;
	passwordRefine: ({
		password,
		refinementContext,
		path,
	}: {
		password: string;
		refinementContext: RefinementCtx;
		path: string;
	}) => void;
	strengthScore: number;
	toggleVisibility: () => void;
	maxStrength: number;
};

export const useStrongPassword = (): PasswordManager => {
	const { t } = useTranslation();

	const [isVisible, setIsVisible] = useState<boolean>(false);
	const [strengthScore, setStrengthScore] = useState(0);

	const checkStrength = (pass: string) => {
		const requirements = [
			{ regex: /.{8,}/, text: t.auth.signup.pw.lenght8 },
			{ regex: /[0-9]/, text: t.auth.signup.pw.number },
			{ regex: /[a-z]/, text: t.auth.signup.pw.lowercase },
			{ regex: /[A-Z]/, text: t.auth.signup.pw.uppercase },
		];

		return requirements.map((req) => ({
			met: req.regex.test(pass),
			text: req.text,
		}));
	};

	const getStrengthColor = (score: number) => {
		if (score === 0) return "bg-border";
		if (score <= 1) return "bg-red-500";
		if (score <= 2) return "bg-orange-500";
		if (score === 3) return "bg-amber-500";
		return "bg-emerald-500";
	};
	const getStrengthTxt = (score: number) => {
		if (score === 0) return "text-border";
		if (score <= 1) return "text-red-500";
		if (score <= 2) return "text-orange-500";
		if (score === 3) return "text-amber-500";
		return "text-emerald-500";
	};

	const toggleVisibility = () => setIsVisible((prevState) => !prevState);

	const passwordRefine = ({
		password,
		refinementContext,
		path,
	}: {
		password: string;
		refinementContext: RefinementCtx;
		path: string;
	}) => {
		const complexity = checkStrength(password);

		if (complexity.filter((req) => req.met).length !== complexity.length) {
			refinementContext.issues.push({
				code: "custom",
				input: "",
				message: complexity
					.filter((req) => !req.met)
					.map((req) => req.text)
					.join("\n"),
				path: [path],
			});
		}
		setStrengthScore(complexity.filter((req) => req.met).length);
	};

	return {
		getStrengthColor,
		getStrengthTxt,
		isVisible,
		passwordRefine,
		strengthScore,
		toggleVisibility,
		maxStrength: 4,
	};
};

export const zMildPassword = z.string().superRefine((password, ctx) => {
	const test = [/.{6,}/, /[a-z]/, /[A-Z]/].every((regex) =>
		regex.test(password),
	);
	if (!test) {
		ctx.addIssue({
			code: "custom",
			message:
				"La password deve contenere almeno 6 caratteri, una lettera minuscola e una maiuscola.",
		});
	}
});

export const useMildPassword = (): PasswordManager => {
	const { t } = useTranslation();

	const [isVisible, setIsVisible] = useState<boolean>(false);
	const [strengthScore, setStrengthScore] = useState(0);

	const checkStrength = (pass: string) => {
		const requirements = [
			{ regex: /.{6,}/, text: t.auth.signup.pw.lenght6 },
			{ regex: /[a-z]/, text: t.auth.signup.pw.lowercase },
			{ regex: /[A-Z]/, text: t.auth.signup.pw.uppercase },
		];

		return requirements.map((req) => ({
			met: req.regex.test(pass),
			text: req.text,
		}));
	};

	const getStrengthColor = (score: number) => {
		if (score === 0) return "bg-border";
		if (score <= 1) return "bg-red-500";
		if (score === 2) return "bg-amber-500";
		return "bg-emerald-500";
	};
	const getStrengthTxt = (score: number) => {
		if (score === 0) return "text-border";
		if (score <= 1) return "text-red-500";
		if (score === 2) return "text-amber-500";
		return "text-emerald-500";
	};

	const toggleVisibility = () => setIsVisible((prevState) => !prevState);

	const passwordRefine = ({
		password,
		refinementContext,
		path,
	}: {
		password: string;
		refinementContext: RefinementCtx;
		path: string;
	}) => {
		const complexity = checkStrength(password);

		if (complexity.filter((req) => req.met).length !== complexity.length) {
			refinementContext.issues.push({
				code: "custom",
				input: "",
				message: complexity
					.filter((req) => !req.met)
					.map((req) => req.text)
					.join("\n"),
				path: [path],
			});
		}
		setStrengthScore(complexity.filter((req) => req.met).length);
	};

	return {
		getStrengthColor,
		getStrengthTxt,
		isVisible,
		passwordRefine,
		strengthScore,
		toggleVisibility,
		maxStrength: 3,
	};
};

export const zPassword = zMildPassword;

export const usePassword = useMildPassword;
