import { useCreateAdmin, useUpdateAdmin } from "@/hooks/queries";
import { ICreateAdminCredentials, userService } from "@/lib/api";
import { extractFileId } from "@/lib/api/config";
import { normalizePhoneFieldValue } from "@/components/FormElements/PhoneNumberInput";
import { validateImageFile } from "@/utils/shared";
import { useIsMutating } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { ChangeEvent, useEffect, useMemo, useRef, useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { toast } from "react-toastify";
import { createAdminFormSections } from "./createAdminFormSections";
import type { CreateAdminFormValues } from "./createAdminForm.types";

export type { CreateAdminFormValues } from "./createAdminForm.types";

interface IProps {
  editMode?: boolean;
  defaultValues?: ICreateAdminCredentials;
  id?: string;
}

const useCreateAdminPresenter = ({
  editMode = false,
  defaultValues,
  id,
}: IProps) => {
  const [passwordFieldInputType, setPasswordFieldInputType] = useState<
    "password" | "text"
  >("password");
  const isMutating = useIsMutating();
  const [selectedFileName, setSelectedFileName] = useState<string>("");
  const [selectedFileSize, setSelectedFileSize] = useState<number | null>(null);
  const [isUploadingImage, setIsUploadingImage] = useState(false);
  const [uploadProgress, setUploadProgress] = useState<number>(0);
  const [uploadedProfileImageUrl, setUploadedProfileImageUrl] = useState<
    string | null | undefined
  >(defaultValues?.profile_image);
  const profileImageInputRef = useRef<HTMLInputElement | null>(null);
  // The existing image rendered as a local (authenticated) object URL — used as
  // the preview baseline so "remove/replace" can fall back to it.
  const [defaultPreviewUrl, setDefaultPreviewUrl] = useState<string | null>(
    null,
  );
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
  const {
    register,
    control,
    formState: { errors },
    handleSubmit,
    watch,
    setError,
    clearErrors,
    setValue,
  } = useForm<CreateAdminFormValues>({
    mode: "onChange",
    defaultValues: {
      ...defaultValues,
      profile_image: undefined,
    },
  });

  const { mutate: createAdmin } = useCreateAdmin();
  const { mutate: updateAdmin } = useUpdateAdmin(id as string);

  const resetToDefaultProfileImage = () => {
    setSelectedFileName("");
    setSelectedFileSize(null);
    setUploadProgress(0);
    setUploadedProfileImageUrl(defaultValues?.profile_image);
    setPreviewUrl(defaultPreviewUrl);
  };

  const validateProfileImage = (file: File): string | null => {
    return validateImageFile({ file });
  };

  const prepareUploadState = (file: File) => {
    clearErrors("profile_image");
    setSelectedFileName(file.name);
    setSelectedFileSize(file.size);
    setIsUploadingImage(true);
    setUploadProgress(0);
    // Preview the local file directly — the backend download URL is
    // auth-protected and cannot be loaded via an <img> tag.
    setPreviewUrl(URL.createObjectURL(file));
  };

  const handleUploadSuccess = (downloadUrl: string) => {
    // Store the absolute backend URL for submission, but keep the local
    // object-URL preview that was set on selection.
    setUploadedProfileImageUrl(downloadUrl);
    setUploadProgress(100);
  };

  const handleUploadFailure = (input: HTMLInputElement) => {
    setUploadedProfileImageUrl(undefined);
    resetToDefaultProfileImage();
    setValue("profile_image", undefined);
    setError("profile_image", {
      type: "validate",
      message: "Failed to upload profile image",
    });
    input.value = "";
  };

  const uploadProfileImage = async (file: File) => {
    return userService.uploadProfileImage({
      file,
      onProgress: (percent) => {
        setUploadProgress(percent);
      },
    });
  };

  const onProfileImageChange = async (event: ChangeEvent<HTMLInputElement>) => {
    const selectedFile = event.target.files?.[0];
    const inputElement = event.target;

    if (!selectedFile) {
      resetToDefaultProfileImage();
      clearErrors("profile_image");
      return;
    }

    const validationError = validateProfileImage(selectedFile);
    if (validationError) {
      setError("profile_image", {
        type: "validate",
        message: validationError,
      });
      inputElement.value = "";
      return;
    }

    prepareUploadState(selectedFile);

    try {
      const downloadUrl = await uploadProfileImage(selectedFile);
      handleUploadSuccess(downloadUrl);
    } catch {
      handleUploadFailure(inputElement);
    } finally {
      setIsUploadingImage(false);
    }
  };

  const clearSelectedProfileImage = () => {
    if (profileImageInputRef.current) {
      profileImageInputRef.current.value = "";
    }
    setValue("profile_image", undefined);
    setSelectedFileName("");
    setSelectedFileSize(null);
    setUploadProgress(0);
    setUploadedProfileImageUrl(null);
    setPreviewUrl(null);
    clearErrors("profile_image");
  };

  // Load the existing (auth-protected) profile image as a local object URL so
  // it can be previewed — a raw <img src> to the download endpoint gets 401.
  useEffect(() => {
    const source = defaultValues?.profile_image;
    if (!source) return;

    // Non-backend URLs (if any) are directly loadable; use them as-is.
    if (!extractFileId(source)) {
      setDefaultPreviewUrl(source);
      setPreviewUrl(source);
      return;
    }

    let cancelled = false;
    userService
      .fetchFileObjectUrl(source)
      .then((objectUrl) => {
        if (cancelled) {
          URL.revokeObjectURL(objectUrl);
          return;
        }
        setDefaultPreviewUrl(objectUrl);
        setPreviewUrl(objectUrl);
      })
      .catch(() => {
        // Leave the preview empty on failure rather than showing a broken image.
      });

    return () => {
      cancelled = true;
    };
  }, [defaultValues?.profile_image]);

  // Revoke the current preview blob when it changes, but never the baseline
  // default preview (it is reused when the user removes/replaces the image).
  useEffect(() => {
    return () => {
      if (previewUrl?.startsWith("blob:") && previewUrl !== defaultPreviewUrl) {
        URL.revokeObjectURL(previewUrl);
      }
    };
  }, [previewUrl, defaultPreviewUrl]);

  // Revoke the baseline default preview blob on unmount.
  useEffect(() => {
    return () => {
      if (defaultPreviewUrl?.startsWith("blob:")) {
        URL.revokeObjectURL(defaultPreviewUrl);
      }
    };
  }, [defaultPreviewUrl]);

  const profileImageRegister = register("profile_image", {
    onChange: onProfileImageChange,
  });
  const profileImageFileRegister = {
    ...profileImageRegister,
    ref: (element: HTMLInputElement | null) => {
      profileImageInputRef.current = element;
      profileImageRegister.ref(element);
    },
  };

  const onSubmit: SubmitHandler<CreateAdminFormValues> = async (data) => {
    const file = data.profile_image?.[0];
    const profileImageUrl = uploadedProfileImageUrl;

    if (file && !profileImageUrl) {
      toast.error("Please wait for profile image upload to finish");
      return;
    }

    const normalizedPhone = normalizePhoneFieldValue(data.phone);

    const payload: ICreateAdminCredentials = {
      ...data,
      phone: normalizedPhone ?? "",
      profile_image: profileImageUrl,
    };

    if (editMode) {
      updateAdmin({ id: id as string, credentials: payload });
    } else {
      createAdmin({ ...payload, role: "admin" });
    }
  };
  const router = useRouter();

  const sections = useMemo(
    () =>
      createAdminFormSections({
        editMode,
        passwordFieldInputType,
        setPasswordFieldInputType,
        profileImageRegister: profileImageFileRegister,
        isUploadingImage,
        uploadProgress,
        previewUrl,
        selectedFileName,
        selectedFileSize,
        clearSelectedProfileImage,
      }),
    [
      editMode,
      passwordFieldInputType,
      profileImageFileRegister,
      isUploadingImage,
      uploadProgress,
      previewUrl,
      selectedFileName,
      selectedFileSize,
      clearSelectedProfileImage,
    ],
  );

  return {
    errors,
    register,
    control,
    handleSubmit,
    router,
    isMutating,
    onSubmit,
    watchForm: watch,
    isUploadingImage,
    uploadProgress,
    selectedFileName,
    selectedFileSize,
    previewUrl,
    clearSelectedProfileImage,
    profileImageRegister: profileImageFileRegister,
    passwordFieldInputType,
    setPasswordFieldInputType,
    sections,
  };
};

export default useCreateAdminPresenter;
