import { useEffect, useMemo, useState, useDeferredValue } from "react";
import { View, Text, ScrollView, GestureResponderEvent } from "react-native";

import { useAuthContext } from "@/auth/AuthContext";
import { Todo } from "@/store/models/Todo.model";
import { LoadingSpinner } from "@/components/ui/LoadingSpinner";
import { NoData } from "@/components/ui/NoData";
import {
  useCreateTodoMutation,
  useDeleteTodoMutation,
  useGetTodosQuery,
  useUpdateTodoMutation,
} from "@/store/api/todosApi";
import { TableSortDirection } from "@/constants/tableSortDirectionEnum";
import { AdminTodosTableControls } from "@/components/features/todos/AdminTodosTableControls";
import { TodoStatus } from "@/constants/todoStatusEnum";
import { TablePagination } from "@/components/shared/TablePagination";
import { useAppSelector } from "@/store/hooks";
import { selectIsMobile } from "@/store/screen/screenSizeSlice";
import { MobileAdminTodosTable } from "@/components/features/todos/MobileAdminTodosTable";
import { DesktopAdminTodosTable } from "@/components/features/todos/DesktopAdminTodosTable";
import { PriorityStatus } from "@/constants/priorityStatusEnum";
import { TodoModal } from "@/components/features/todos/TodoModal";
import { DeleteTodoModal } from "@/components/features/todos/DeleteTodoModal";
import { OperationMode } from "@/constants/operationModeEnum";
import { AppSnackbar } from "@/components/ui/AppSnackbar";

interface CreateTodoPayload {
  title: string;
  task: string;
  status: TodoStatus;
  priority: PriorityStatus;
  dueDate: Date;
  createdById: string;
  assigneeIds: string[];
}

export const AdminTodosTable = ({ initialSearchQuery = "" }: { initialSearchQuery?: string }) => {
  const { user } = useAuthContext();
  const [page, setPage] = useState(0);
  const [itemsPerPage, setItemsPerPage] = useState(25);
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedStatuses, setSelectedStatuses] = useState<TodoStatus[]>([]);
  const [selectedPriorities, setSelectedPriorities] = useState<
    PriorityStatus[]
  >([]);
  const [sortColumn, setSortColumn] = useState<string | null>(null);
  const [sortDirection, setSortDirection] = useState<TableSortDirection>(
    TableSortDirection.ASCENDING
  );

  const deferredSearch = useDeferredValue(searchQuery);
  const [debouncedSearch, setDebouncedSearch] = useState("");
  useEffect(() => {
    const t = setTimeout(() => setDebouncedSearch(deferredSearch.trim()), 450);
    return () => clearTimeout(t);
  }, [deferredSearch]);

  // Initialize search from route param if provided
  useEffect(() => {
    const q = (initialSearchQuery || "").trim();
    if (q && q !== searchQuery) {
      setSearchQuery(q);
      setPage(0);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [initialSearchQuery]);

  const queryArgs = useMemo(() => {
    const allowedSorts = [
      "title",
      "dueDate",
      "status",
      "priority",
      "createdAt",
    ] as const;
    const sortBy = (allowedSorts as readonly string[]).includes(
      sortColumn || ""
    )
      ? (sortColumn as (typeof allowedSorts)[number])
      : undefined;
    const sortDir = sortDirection;
    const searchParam =
      debouncedSearch && debouncedSearch.length >= 2
        ? debouncedSearch
        : undefined;
    return {
      page: page + 1,
      limit: itemsPerPage,
      search: searchParam,
      statuses: selectedStatuses.length ? selectedStatuses : undefined,
      priorities: selectedPriorities.length ? selectedPriorities : undefined,
      sortBy,
      sortDir,
    };
  }, [
    page,
    itemsPerPage,
    debouncedSearch,
    selectedStatuses,
    selectedPriorities,
    sortColumn,
    sortDirection,
  ]);

  const {
    data: todosPage,
    isLoading,
    isFetching,
    error,
    refetch,
  } = useGetTodosQuery(queryArgs);
  const todos = todosPage?.items ?? [];
  const totalItems = todosPage?.total ?? 0;


  const [createTodo, { isLoading: isCreatingTodo }] = useCreateTodoMutation();
  const [updateTodo, { isLoading: isUpdatingTodo }] = useUpdateTodoMutation();
  const [deleteTodo, { isLoading: isDeletingTodo }] = useDeleteTodoMutation();

  const [menuVisible, setMenuVisible] = useState(false);
  const [menuAnchor, setMenuAnchor] = useState<{ x: number; y: number }>({
    x: 0,
    y: 0,
  });
  const [addTodoModalVisible, setAddTodoModalVisible] = useState(false);
  const [editTodoModalVisible, setEditTodoModalVisible] = useState(false);
  const [deleteTodoModalVisible, setDeleteTodoModalVisible] = useState(false);
  const [currentTodo, setCurrentTodo] = useState<Todo | null>(null);
  const [snackbarVisible, setSnackbarVisible] = useState(false);
  const [snackbarMessage, setSnackbarMessage] = useState("");

  const showSnackbar = (message: string) => {
    setSnackbarMessage(message);
    setSnackbarVisible(true);
  };

  const handleCreateTodo = async (
    todo: Partial<Todo> & { assigneeIds?: string[]; userId?: string }
  ) => {
    try {
      const unique = (arr: string[]) => Array.from(new Set(arr.filter(Boolean)));
      const payload: CreateTodoPayload = {
        title: todo.title || "",
        task: todo.task || "",
        status: todo.status || TodoStatus.NEW,
        priority: todo.priority || PriorityStatus.LOW_PRIORITY,
        dueDate: todo.dueDate || new Date(),
        createdById: user?.id || "",
        assigneeIds: unique([...(todo.assigneeIds || []), ...(todo.userId ? [todo.userId] : [])]),
      };

      await createTodo(payload).unwrap();
      showSnackbar("Todo created successfully");
      setAddTodoModalVisible(false);
      refetch();
    } catch {
      showSnackbar("Error creating todo");
    }
  };

  const handleUpdateTodo = async (
    todo: Partial<Todo> & { assigneeIds?: string[]; userId?: string }
  ) => {
    try {
      const body: any = {
        ...(todo.id ? { id: todo.id } : {}),
        ...(todo.title ? { title: todo.title } : {}),
        ...(todo.task ? { task: todo.task } : {}),
        ...(todo.status ? { status: todo.status } : {}),
        ...(todo.priority ? { priority: todo.priority } : {}),
        ...(todo.dueDate ? { dueDate: todo.dueDate } : {}),
      };
      const combinedAssignees = Array.from(
        new Set([...(todo.assigneeIds || []), ...(todo.userId ? [todo.userId] : [])])
      );
      if (combinedAssignees.length) {
        body.assigneeIds = combinedAssignees;
      }
      await updateTodo(body).unwrap();
      showSnackbar("Todo updated successfully");
      setEditTodoModalVisible(false);
      refetch();
    } catch {
      showSnackbar("Error updating todo");
    }
  };

  const handleDeleteTodo = async (todo: Todo) => {
    try {
      await deleteTodo(todo.id).unwrap();
      refetch();
      showSnackbar(`${todo.title} has been deleted successfully`);
      setDeleteTodoModalVisible(false);
    } catch {
      showSnackbar("Error deleting todo");
    }
  };

  const handleSort = (column: string) => {
    setSortColumn(column);
    setSortDirection(
      sortDirection === TableSortDirection.ASCENDING
        ? TableSortDirection.DESCENDING
        : TableSortDirection.ASCENDING
    );
    setPage(0);
  };

  const handleItemsPerPageChange = (value: number) => {
    setItemsPerPage(value);
  };

  const handleSearch = (query: string) => {
    setSearchQuery(query);
    setPage(0);
  };

  const handleEdit = (todo: Todo) => {
    setCurrentTodo(todo);
    setEditTodoModalVisible(true);
  };

  const openDeleteModal = (todo: Todo) => {
    setCurrentTodo(todo);
    setDeleteTodoModalVisible(true);
  };

  const isMobile = useAppSelector(selectIsMobile);

  const from = todos.length ? page * itemsPerPage + 1 : 0;
  const to = todos.length ? Math.min(from + todos.length - 1, totalItems) : 0;

  useEffect(() => {
    setPage(0);
  }, [itemsPerPage]);

  return (
    <>
      <View className="flex-1">
        <Text
          className={`text-2xl font-bold ${
            isMobile ? "mb-1" : "mb-4"
          } text-white`}
        >
          Todos manager
        </Text>
        <View
          className={`${
            isMobile ? "p-1" : "p-5"
          } bg-lightGray rounded-lg flex-1`}
        >
          {isLoading ? (
            <View className="flex-1 justify-center items-center">
              <LoadingSpinner />
              <Text className="mt-2">Loading todos...</Text>
            </View>
          ) : error ? (
            <NoData
              message="Error loading todos"
              onRetry={refetch}
              isRetrying={isFetching}
            />
          ) : (
            <View className="flex-1 flex flex-col">
              <AdminTodosTableControls
                searchQuery={searchQuery}
                menuVisible={menuVisible}
                menuAnchor={menuAnchor}
                selectedStatuses={selectedStatuses}
                selectedPriorities={selectedPriorities}
                onSearch={handleSearch}
                onMenuDismiss={() => setMenuVisible(false)}
                onItemsPerPageChange={handleItemsPerPageChange}
                onSelectStatuses={setSelectedStatuses}
                onSelectPriorities={setSelectedPriorities}
                onAddTodo={() => setAddTodoModalVisible(true)}
                itemsPerPage={itemsPerPage}
              />

              <TodoModal
                visible={addTodoModalVisible}
                onClose={() => setAddTodoModalVisible(false)}
                onSubmit={handleCreateTodo}
                isLoading={isCreatingTodo}
                mode={OperationMode.ADD}
              />

              <TodoModal
                visible={editTodoModalVisible}
                todo={currentTodo}
                onClose={() => setEditTodoModalVisible(false)}
                onSubmit={handleUpdateTodo}
                isLoading={isUpdatingTodo}
                mode={OperationMode.EDIT}
              />

              <DeleteTodoModal
                visible={deleteTodoModalVisible}
                todo={currentTodo}
                onDismiss={() => setDeleteTodoModalVisible(false)}
                onDelete={handleDeleteTodo}
                isLoading={isDeletingTodo}
              />

              <View className="flex-1 overflow-hidden">
                {searchQuery && todos.length === 0 ? (
                  <View
                    className={`flex-1 items-center justify-center ${
                      isMobile ? "p-1" : "p-5"
                    }`}
                  >
                    <Text className="text-lg text-gray-500">
                      No todos match your search for &quot;{searchQuery}&quot;
                    </Text>
                  </View>
                ) : searchQuery.length === 0 && todos.length === 0 ? (
                  <View
                    className={`flex-1 items-center justify-center ${
                      isMobile ? "p-1" : "p-5"
                    }`}
                  >
                    <Text className="text-lg text-gray-500">
                      No todos found
                    </Text>
                  </View>
                ) : isMobile ? (
                  <View className="flex-1">
                    <MobileAdminTodosTable
                      todos={todos}
                      onEdit={handleEdit}
                      onDelete={openDeleteModal}
                    />
                  </View>
                ) : (
                  <View className="flex-1" style={{ height: 400 }}>
                    <ScrollView className="flex-1">
                      <DesktopAdminTodosTable
                        todos={todos}
                        sortColumn={sortColumn}
                        sortDirection={sortDirection}
                        onSort={handleSort}
                        onEdit={handleEdit}
                        onDelete={openDeleteModal}
                      />
                    </ScrollView>
                  </View>
                )}
              </View>
              <TablePagination
                page={page}
                itemsPerPage={itemsPerPage}
                totalItems={totalItems}
                from={from}
                to={to}
                onPageChange={setPage}
                onItemsPerPageButtonPress={(event: GestureResponderEvent) => {
                  const { pageX, pageY } = event.nativeEvent;
                  setMenuAnchor({ x: pageX, y: pageY });
                  setMenuVisible(true);
                }}
              />
            </View>
          )}
        </View>
      </View>

      <AppSnackbar
        visible={snackbarVisible}
        onDismiss={() => setSnackbarVisible(false)}
        action={{ label: "Close", onPress: () => setSnackbarVisible(false) }}
      >
        {snackbarMessage}
      </AppSnackbar>
    </>
  );
};
