"use client";

import { SortDirection } from "@/components/ui/tableSortContext";
import {
  useAssignCompany,
  useCompaniesInfiniteQuery,
  useCompanyFullList,
  useCustomersQuery,
  useDeleteCustomerQuery,
  useResetCustomerPassword,
} from "@/hooks/queries";
import useDebounce from "@/hooks/useDebounce";
import { useHybridPagination } from "@/hooks/useHybridPagination";
import { useTableSectionRowAnimations } from "@/hooks/useTableSectionRowAnimations";
import { TAssignCustomerToCompanyCredentials, TCustomer } from "@/lib/api";
import { apiDefaultParams } from "@/constants/Api_Params";
import { buildQueryString, deleteEmptyKeys } from "@/utils/shared";
import { useIsMutating } from "@tanstack/react-query";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";

const useCustomerListPresenter = () => {
  const [isAssignCompanyModalOpen, setIsAssignCompanyModalOpen] =
    useState(false);
  const [selectedCompanies, setSelectedCompanies] = useState<
    TAssignCustomerToCompanyCredentials | undefined
  >();
  const [currentCustomer, setCurrentCustomer] = useState<TCustomer | null>(
    null,
  );

  const [isModalOpen, setIsModalOpen] = useState(false);
  const [isResetPasswordModalOpen, setIsResetPasswordModalOpen] =
    useState(false);
  const [generatedPassword, setGeneratedPassword] = useState<string | null>(
    null,
  );
  const pathName = usePathname();
  const searchParams = useSearchParams();
  const [params, setParams] = useState<Record<string, any>>({
    ...apiDefaultParams,
  });
  const router = useRouter();
  const isMutating = useIsMutating();

  const {
    register: filterRegister,
    handleSubmit: handleFilterSubmit,
    reset: filterFormReset,
    watch,
    setValue: setFilterValue,
  } = useForm();

  // Lazy-loaded company options for the inline filter dropdown.
  const [companySearch, setCompanySearch] = useState("");
  const debouncedCompanySearch = useDebounce(companySearch, 400);
  const companiesQuery = useCompaniesInfiniteQuery(
    debouncedCompanySearch ? { search: debouncedCompanySearch } : undefined,
  );

  const companyItems = useMemo(
    () =>
      companiesQuery.data?.pages.flatMap(
        (page) =>
          page.data.companies?.map((company) => ({
            label: company.name,
            value: company.id,
          })) ?? [],
      ) ?? [],
    [companiesQuery.data],
  );

  const onCompanySearch = useCallback((query: string) => {
    setCompanySearch(query);
  }, []);

  const onCompanyLoadMore = useCallback(() => {
    if (companiesQuery.hasNextPage && !companiesQuery.isFetchingNextPage) {
      companiesQuery.fetchNextPage();
    }
  }, [companiesQuery]);

  const tableSectionRef = useRef<HTMLDivElement>(null);
  const skeletonTbodyRef = useRef<HTMLTableSectionElement>(null);
  const dataTbodyRef = useRef<HTMLTableSectionElement>(null);

  useEffect(() => {
    const newParams: Record<string, any> = {
      ...apiDefaultParams,
      offset: 0,
      limit: 10,
    };
    for (const [key, value] of searchParams.entries()) {
      newParams[key] = value;
    }
    setParams(newParams);
    filterFormReset(newParams);
  }, [searchParams, filterFormReset]);

  const { data, isPending, isError, error } = useCustomersQuery(params);

  const { pagination, handlePaginationChange, buildFirstPageParams } =
    useHybridPagination({
      meta: data?.meta,
      params,
      setParams,
      isError,
      error,
    });

  useTableSectionRowAnimations(isPending, data, {
    tableSectionRef,
    skeletonTbodyRef,
    dataTbodyRef,
  });

  const assignCompanyCompaniesQuery = useCompanyFullList({
    enabled: isAssignCompanyModalOpen,
  });
  const { mutate: deleteCustomer } = useDeleteCustomerQuery(() =>
    setIsModalOpen(false),
  );
  const { mutate: assignSelectedCompanies } = useAssignCompany(
    currentCustomer?.id ?? "",
    () => {
      setIsAssignCompanyModalOpen(false);
    },
  );

  const { mutate: resetCustomerPassword, isPending: isResettingPassword } =
    useResetCustomerPassword({
      successCallback: (password) => setGeneratedPassword(password),
    });

  const openResetPasswordModalForCustomer = useCallback(
    (customer: TCustomer) => {
      setCurrentCustomer(customer);
      setGeneratedPassword(null);
      setIsResetPasswordModalOpen(true);
      resetCustomerPassword(customer.id);
    },
    [resetCustomerPassword],
  );

  const closeResetPasswordModal = useCallback(() => {
    setIsResetPasswordModalOpen(false);
    setGeneratedPassword(null);
  }, []);

  const search = (formData: any) => {
    const newParams = buildFirstPageParams({ ...params, ...formData });
    const cleanedParams = deleteEmptyKeys(newParams);
    const queryString = new URLSearchParams(cleanedParams).toString();
    router.push(`${pathName}?${queryString}`);
  };

  const clearAllFilters = useCallback(() => {
    filterFormReset({
      status: undefined,
      role: undefined,
      type: undefined,
      full_name: "",
      email: "",
      company_id: undefined,
    });
    setCompanySearch("");
    router.push(pathName);
  }, [pathName, router, filterFormReset]);

  const columns = [
    "row",
    "full name",
    "email",
    "created at",
    "type",
    "status",
    "company",
    "role",
    "actions",
  ];
  const onConfirmDelete = () => {
    if (currentCustomer) {
      deleteCustomer(currentCustomer.id);
    }
  };

  /** Column label → BSON `sort_by` field. */
  const columnSortKeys: Record<string, string> = {
    "full name": "full_name",
    email: "email",
    "created at": "created_at",
    type: "type",
    status: "status",
    role: "role",
  };

  /** First-click direction per column. */
  const columnDefaultOrder: Record<string, SortDirection> = {
    "full name": "asc",
    email: "asc",
    type: "asc",
    role: "asc",
    "created at": "desc",
  };

  const sortBy = (params.sort_by as string) ?? "created_at";
  const sortOrder = (params.sort_order as SortDirection) ?? "desc";

  const handleSortChange = useCallback(
    (key: string, order: SortDirection) => {
      const newParams = buildFirstPageParams({
        ...params,
        sort_by: key,
        sort_order: order,
      });
      const cleanedParams = deleteEmptyKeys(newParams);
      const queryString = buildQueryString(cleanedParams);
      router.push(`${pathName}?${queryString}`);
    },
    [buildFirstPageParams, params, pathName, router],
  );

  const customers = data?.data?.customers ?? [];
  const shouldShowPagination =
    !isPending && (data?.meta?.pages ?? 1) * (data?.meta?.limit ?? 10) > 10;

  return {
    allCustomers: customers,
    metadata: data?.meta,
    currentCustomer,
    columns,
    columnSortKeys,
    columnDefaultOrder,
    sortBy,
    sortOrder,
    handleSortChange,
    isPending,
    setCurrentCustomer,
    selectedCompanies,
    setSelectedCompanies,
    onConfirmDelete,
    setIsAssignCompanyModalOpen,
    isAssignCompanyModalOpen,
    assignSelectedCompanies,
    pathName,
    router,
    isModalOpen,
    setIsModalOpen,
    filterRegister,
    handleFilterSubmit,
    search,
    watch,
    setFilterValue,
    isMutating,
    setParams,
    assignCompanyCompaniesQuery,
    shouldShowPagination,
    clearAllFilters,
    tableSectionRef,
    skeletonTbodyRef,
    dataTbodyRef,
    pagination,
    handlePaginationChange,
    isResetPasswordModalOpen,
    closeResetPasswordModal,
    openResetPasswordModalForCustomer,
    generatedPassword,
    isResettingPassword,
    companyItems,
    onCompanySearch,
    onCompanyLoadMore,
    companyHasMore: companiesQuery.hasNextPage,
    companyIsLoading:
      companiesQuery.isFetching && !companiesQuery.isFetchingNextPage,
    companyIsLoadingMore: companiesQuery.isFetchingNextPage,
  };
};

export default useCustomerListPresenter;
