"use client";
import {
  NotificationChannels,
  NotificationPriorities,
  NotificationTargetGroups,
  NotificationTypes,
} from "@/constants/enums";
import {
  useAdminListInfiniteQuery,
  useCompaniesInfiniteQuery,
  useCustomersInfiniteQuery,
} from "@/hooks/queries";
import useDebounce from "@/hooks/useDebounce";
import { useCreateNotificationQuery } from "@/hooks/queries/useNotificationQueries";
import { TCreateNotificationCredentials } from "@/lib/api/types/NotificationHistory";
import { ILabelValue } from "@/types/shared";
import { getEnumAsArray } from "@/utils/shared";
import { useRouter } from "next/navigation";
import { ChangeEvent, useCallback, useMemo, useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";

const ROLE_ITEMS: ILabelValue[] = [
  { label: "Admin", value: "admin" },
  { label: "Analyst", value: "analyst" },
];

const useCreateNotificationFormPresenter = () => {
  const [target, setTarget] = useState<NotificationTargetGroups | null>(null);
  const [recipientSearch, setRecipientSearch] = useState("");
  const debouncedSearch = useDebounce(recipientSearch, 400);

  const {
    register,
    formState: { errors },
    handleSubmit,
    watch,
    setValue,
    reset,
    control,
  } = useForm<TCreateNotificationCredentials>();
  const router = useRouter();

  const isCompany = target === NotificationTargetGroups.SPECIFIC_COMPANY;
  const isUser = target === NotificationTargetGroups.SPECIFIC_USERS;
  const isCustomer = target === NotificationTargetGroups.SPECIFIC_CUSTOMER;

  const searchParam = debouncedSearch ? { search: debouncedSearch } : undefined;

  const companiesQuery = useCompaniesInfiniteQuery(searchParam, {
    enabled: isCompany,
  });
  const usersQuery = useAdminListInfiniteQuery(searchParam, {
    enabled: isUser,
  });
  const customersQuery = useCustomersInfiniteQuery(searchParam, {
    enabled: isCustomer,
  });

  const companiesItems = useMemo(() => {
    if (!companiesQuery.data) return null;
    return companiesQuery.data.pages.flatMap(
      (page) =>
        page.data.companies?.map((c) => ({ label: c.name, value: c.id })) ?? [],
    );
  }, [companiesQuery.data]);

  const usersItems = useMemo(() => {
    if (!usersQuery.data) return null;
    return usersQuery.data.pages.flatMap(
      (page) =>
        page.data.users?.map((u) => ({
          label: u.full_name ?? u.username ?? u.id,
          value: u.id,
        })) ?? [],
    );
  }, [usersQuery.data]);

  const customersItems = useMemo(() => {
    if (!customersQuery.data) return null;
    return customersQuery.data.pages.flatMap(
      (page) =>
        page.data.customers?.map((c) => ({
          label: c.full_name,
          value: c.id,
        })) ?? [],
    );
  }, [customersQuery.data]);

  const recipient = useMemo((): ILabelValue[] | null => {
    if (!target) return null;
    const map: Partial<Record<NotificationTargetGroups, ILabelValue[] | null>> =
      {
        [NotificationTargetGroups.SPECIFIC_COMPANY]: companiesItems,
        [NotificationTargetGroups.SPECIFIC_USERS]: usersItems,
        [NotificationTargetGroups.SPECIFIC_CUSTOMER]: customersItems,
        [NotificationTargetGroups.SPECIFIC_ROLE]: ROLE_ITEMS,
      };
    return map[target] ?? null;
  }, [target, companiesItems, usersItems, customersItems]);

  const hasMoreRecipients = useMemo(() => {
    if (isCompany) return companiesQuery.hasNextPage;
    if (isUser) return usersQuery.hasNextPage;
    if (isCustomer) return customersQuery.hasNextPage;
    return false;
  }, [
    isCompany,
    isUser,
    isCustomer,
    companiesQuery.hasNextPage,
    usersQuery.hasNextPage,
    customersQuery.hasNextPage,
  ]);

  const isLoadingMoreRecipients = useMemo(() => {
    if (isCompany) return companiesQuery.isFetchingNextPage;
    if (isUser) return usersQuery.isFetchingNextPage;
    if (isCustomer) return customersQuery.isFetchingNextPage;
    return false;
  }, [
    isCompany,
    isUser,
    isCustomer,
    companiesQuery.isFetchingNextPage,
    usersQuery.isFetchingNextPage,
    customersQuery.isFetchingNextPage,
  ]);

  // True during initial/search fetches (not load-more)
  const isLoadingRecipients = useMemo(() => {
    if (isCompany)
      return companiesQuery.isFetching && !companiesQuery.isFetchingNextPage;
    if (isUser) return usersQuery.isFetching && !usersQuery.isFetchingNextPage;
    if (isCustomer)
      return customersQuery.isFetching && !customersQuery.isFetchingNextPage;
    return false;
  }, [
    isCompany,
    isUser,
    isCustomer,
    companiesQuery.isFetching,
    companiesQuery.isFetchingNextPage,
    usersQuery.isFetching,
    usersQuery.isFetchingNextPage,
    customersQuery.isFetching,
    customersQuery.isFetchingNextPage,
  ]);

  const onLoadMoreRecipients = useCallback(() => {
    if (isCompany) companiesQuery.fetchNextPage();
    else if (isUser) usersQuery.fetchNextPage();
    else if (isCustomer) customersQuery.fetchNextPage();
  }, [isCompany, isUser, isCustomer, companiesQuery, usersQuery, customersQuery]);

  const onSearchRecipient = useCallback((query: string) => {
    setRecipientSearch(query);
  }, []);

  const { mutate } = useCreateNotificationQuery(() => {
    router.back();
    reset();
  });

  const onSubmit: SubmitHandler<TCreateNotificationCredentials> = (data) => {
    const credentials = {
      ...data,
      schedule_at: data.schedule_at || 0,
    };
    mutate({ credentials });
  };

  const handleCancel = () => {
    reset();
    router.back();
  };

  const onSelectTarget = (event: ChangeEvent<HTMLSelectElement>): void => {
    const type = event.target.value as NotificationTargetGroups;
    setTarget(type);
    setRecipientSearch("");
    setValue("recipient", undefined);
  };

  return {
    handleSubmit,
    watch,
    priorities: getEnumAsArray(NotificationPriorities),
    handleCancel,
    router,
    setValue,
    reset,
    register,
    errors,
    onSelectTarget,
    onSubmit,
    control,
    recipient,
    onSearchRecipient,
    onLoadMoreRecipients,
    hasMoreRecipients,
    isLoadingMoreRecipients,
    isLoadingRecipients,
    targets: getEnumAsArray(NotificationTargetGroups),
    types: getEnumAsArray(NotificationTypes),
    channels: getEnumAsArray(NotificationChannels),
  };
};

export default useCreateNotificationFormPresenter;
