"use client";

import React from "react";

import { adminCreateUser, ApiClientError } from "@/lib/frontend/apiClient";
import { buildLoginUrl, LOGIN_REASONS } from "@/lib/frontend/authRedirect";
import {
	notifySuccess,
	notifyError,
	notifyApiError,
} from "@/lib/frontend/ui/toast";

import {
	getPasswordPolicyHintLinesDe,
	reasonsToHintLinesDe,
	buildWeakPasswordMessageDe,
} from "@/lib/frontend/profile/passwordPolicyUi";
import { useSearchBranches } from "@/lib/frontend/search/useSearchBranches";
import {
	evaluateBranchExistence,
	normalizeBranchIdInput,
	isValidBranchIdFormat,
} from "@/lib/frontend/admin/users/userManagementUx";

import {
	CREATE_ROLE_OPTIONS,
	EMAIL_RE,
	normalizeUsername,
	normalizeEmail,
} from "@/components/admin/users/create-user/createUserUtils";

const DEFAULT_FORM = Object.freeze({
	username: "",
	email: "",
	role: "branch",
	branchId: "",
	initialPassword: "",
});

function cloneDefaultForm() {
	return { ...DEFAULT_FORM };
}

function validateClient(form) {
	const username = normalizeUsername(form?.username);
	const email = normalizeEmail(form?.email);
	const role = String(form?.role || "").trim();
	const branchId = role === "branch" ? normalizeBranchIdInput(form?.branchId) : "";
	const initialPassword = String(form?.initialPassword || "");

	if (!username) return { title: "Benutzername fehlt.", description: null };
	if (!email) return { title: "E-Mail fehlt.", description: null };
	if (!EMAIL_RE.test(email)) {
		return {
			title: "E-Mail ist ungültig.",
			description: "Bitte prüfen Sie die Eingabe.",
		};
	}

	const isKnownRole = CREATE_ROLE_OPTIONS.some((x) => x.value === role);
	if (!role || !isKnownRole)
		return { title: "Rolle fehlt.", description: null };

	if (role === "branch") {
		if (!branchId) {
			return {
				title: "Niederlassung fehlt.",
				description: "Für Niederlassungs-User ist eine NL erforderlich.",
			};
		}
		if (!isValidBranchIdFormat(branchId)) {
			return {
				title: "Niederlassung ist ungültig.",
				description: "Format: NL01, NL02, ...",
			};
		}
	}

	if (!initialPassword.trim()) {
		return { title: "Initiales Passwort fehlt.", description: null };
	}

	return null;
}

function extractDuplicateFields(details) {
	if (!details || typeof details !== "object") return [];

	// Accept both shapes:
	// - { field: "username" }
	// - { fields: ["username","email"] }
	const one =
		typeof details.field === "string" && details.field.trim()
			? details.field.trim()
			: null;

	const many = Array.isArray(details.fields)
		? details.fields.map((x) => String(x))
		: null;

	const list = many ?? (one ? [one] : []);
	return Array.from(new Set(list.map(String)));
}

function mapDuplicateFieldsToGermanMessage(fields) {
	const hasUsername = fields.includes("username");
	const hasEmail = fields.includes("email");

	if (!hasUsername && !hasEmail) return null;

	if (hasUsername && hasEmail) {
		return {
			title: "Benutzername und E-Mail existieren bereits.",
			description: "Bitte wählen Sie andere Werte und versuchen Sie es erneut.",
		};
	}

	if (hasUsername) {
		return {
			title: "Benutzername existiert bereits.",
			description: "Bitte wählen Sie einen anderen Benutzernamen.",
		};
	}

	return {
		title: "E-Mail existiert bereits.",
		description: "Bitte wählen Sie eine andere E-Mail-Adresse.",
	};
}

export function useCreateUserDialog({ disabled = false, onCreated } = {}) {
	const [open, setOpen] = React.useState(false);
	const [isSubmitting, setIsSubmitting] = React.useState(false);
	const [form, setForm] = React.useState(() => cloneDefaultForm());
	const [error, setError] = React.useState(null);

	const policyLines = React.useMemo(() => getPasswordPolicyHintLinesDe(), []);
	const role = String(form?.role || "branch").trim();
	const shouldLoadBranches = open && role === "branch";
	const { status: branchesStatus, branches: availableBranchIds } =
		useSearchBranches({ enabled: shouldLoadBranches });

	const effectiveDisabled = Boolean(disabled || isSubmitting);
	const branchExistence = React.useMemo(
		() =>
			evaluateBranchExistence({
				role,
				branchId: form?.branchId,
				branchesStatus,
				availableBranchIds,
			}),
		[role, form?.branchId, branchesStatus, availableBranchIds],
	);
	const canSubmit = !effectiveDisabled && !branchExistence.shouldBlockSubmit;

	const setPatch = React.useCallback((patch) => {
		setForm((prev) => ({ ...prev, ...(patch || {}) }));
	}, []);

	const resetForm = React.useCallback(() => {
		setForm(cloneDefaultForm());
		setError(null);
	}, []);

	const redirectToLoginExpired = React.useCallback(() => {
		const next =
			typeof window !== "undefined"
				? `${window.location.pathname}${window.location.search}`
				: "/admin/users";

		window.location.replace(
			buildLoginUrl({ reason: LOGIN_REASONS.EXPIRED, next }),
		);
	}, []);

	const handleOpenChange = React.useCallback(
		(nextOpen) => {
			setOpen(nextOpen);
			if (!nextOpen) resetForm();
		},
		[resetForm],
	);

	const handleSubmit = React.useCallback(
		async (e) => {
			e?.preventDefault?.();
			if (effectiveDisabled) return;

			setError(null);

			const clientErr = validateClient(form);
			if (clientErr) {
				setError(clientErr);
				notifyError({
					title: clientErr.title,
					description: clientErr.description,
				});
				return;
			}

			if (branchExistence.shouldBlockSubmit) {
				const mapped = {
					title: "Niederlassung existiert nicht.",
					description:
						"Die gewählte Niederlassung ist nicht in der aktuellen Liste vorhanden.",
				};
				setError(mapped);
				notifyError(mapped);
				return;
			}

			setIsSubmitting(true);

			try {
				const username = normalizeUsername(form.username);
				const email = normalizeEmail(form.email);
				const role = String(form.role || "").trim();

				const branchId =
					role === "branch" ? normalizeBranchIdInput(form.branchId) : null;

				const initialPassword = String(form.initialPassword || "");

				await adminCreateUser({
					username,
					email,
					role,
					branchId,
					initialPassword,
				});

				notifySuccess({
					title: "Benutzer angelegt",
					description: `Benutzer "${username}" wurde erstellt.`,
				});

				setOpen(false);
				resetForm();

				if (typeof onCreated === "function") onCreated();
			} catch (err) {
				if (err instanceof ApiClientError) {
					if (err.code === "AUTH_UNAUTHENTICATED") {
						notifyApiError(err);
						redirectToLoginExpired();
						return;
					}

					if (err.code === "VALIDATION_WEAK_PASSWORD") {
						const reasons = err.details?.reasons;
						const minLength = err.details?.minLength;

						const hints = reasonsToHintLinesDe({ reasons, minLength });
						const description = buildWeakPasswordMessageDe({
							reasons,
							minLength,
						});

						setError({
							title: "Passwort ist zu schwach.",
							description,
							hints,
						});

						notifyError({ title: "Passwort ist zu schwach.", description });
						return;
					}

					// Precise duplicate feedback (username/email)
					if (err.code === "VALIDATION_INVALID_FIELD") {
						const fields = extractDuplicateFields(err.details);
						const mapped = mapDuplicateFieldsToGermanMessage(fields);

						if (mapped) {
							setError(mapped);
							notifyError(mapped);
							return;
						}
					}

					setError({
						title: "Benutzer konnte nicht angelegt werden.",
						description:
							"Bitte prüfen Sie die Eingaben und versuchen Sie es erneut.",
					});

					notifyApiError(err, {
						fallbackTitle: "Benutzer konnte nicht angelegt werden.",
						fallbackDescription:
							"Bitte prüfen Sie die Eingaben und versuchen Sie es erneut.",
					});
					return;
				}

				setError({
					title: "Benutzer konnte nicht angelegt werden.",
					description: "Bitte versuchen Sie es erneut.",
				});

				notifyError({
					title: "Benutzer konnte nicht angelegt werden.",
					description: "Bitte versuchen Sie es erneut.",
				});
			} finally {
				setIsSubmitting(false);
			}
		},
		[
			effectiveDisabled,
			form,
			onCreated,
			redirectToLoginExpired,
			resetForm,
			branchExistence.shouldBlockSubmit,
		],
	);

	return {
		open,
		setOpen,
		form,
		setPatch,
		error,
		policyLines,
		branchesStatus,
		branchExistence,
		isSubmitting,
		effectiveDisabled,
		canSubmit,
		handleSubmit,
		handleOpenChange,
	};
}
