import { useState, useEffect, useRef } from "react";
import { View, Text, ScrollView, Dimensions } from "react-native";
import { Dialog, TextInput, IconButton } from "react-native-paper";
import { DatePickerInput, TimePickerModal } from "react-native-paper-dates";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";

import { Button } from "@/components/ui/Button";
import { LoadingSpinner } from "@/components/ui/LoadingSpinner";
import { Todo } from "@/store/models/Todo.model";
import { PriorityStatus } from "@/constants/priorityStatusEnum";
import { TodoStatus } from "@/constants/todoStatusEnum";
import { SizeEnum } from "@/constants/sizeEnum";
import { OperationMode } from "@/constants/operationModeEnum";
import { useAppSelector } from "@/store/hooks";
import { selectIsMobile } from "@/store/screen/screenSizeSlice";
import { DialogContainer } from "@/components/ui/DialogContainer";
import { CustomPicker, PickerItem } from "@/components/ui/CustomPicker";
import {
  SearchableDropdown,
  DropdownItem,
} from "@/components/ui/SearchableDropdown";
import { useGetUsersQuery } from "@/store/api/usersApi";
import { User } from "@/store/models/User.model";
import { RoleEnum } from "@/constants/roleEnum";
import {
  todoSchema,
  TodoFormValues,
} from "@/components/features/todos/schemas/todo.schema";

interface TodoModalProps {
  visible: boolean;
  onClose: () => void;
  onSubmit: (
    todo: Partial<Todo> & { assigneeIds?: string[]; userId?: string },
  ) => void;
  isLoading: boolean;
  todo?: Todo | null;
  mode: OperationMode;
}

export const TodoModal = ({
  visible,
  onClose,
  onSubmit,
  isLoading,
  todo = null,
  mode = OperationMode.ADD,
}: TodoModalProps) => {
  const todoRef = useRef<Todo | null>(todo);
  todoRef.current = todo;
  // Helpers to extract existing selections from the todo
  const existingSupervisors = (todo?.assignees ?? []).filter(
    (u) => u.role === RoleEnum.ADMIN || u.role === RoleEnum.MANAGER,
  );
  const existingUser = (todo?.assignees ?? []).find(
    (u) => u.role === RoleEnum.USER,
  );
  const defaultValues: TodoFormValues = {
    id: todo?.id,
    title: todo?.title ?? "",
    task: todo?.task ?? "",
    priority: (todo?.priority ?? "LOW_PRIORITY") as PriorityStatus,
    status: (todo?.status ?? "NEW") as TodoStatus,
    dueDate: todo?.dueDate ? new Date(todo.dueDate) : new Date(),
    // Only supervisors (Admin/Manager) go into assigneeIds; regular user goes into userId
    assigneeIds: existingSupervisors.map((u) => u.id),
    userId: existingUser?.id,
  };

  const {
    control,
    handleSubmit,
    reset,
    watch,
    setValue,
    formState: { errors, isDirty, isValid },
  } = useForm<TodoFormValues>({
    resolver: zodResolver(todoSchema),
    defaultValues,
    mode: "onChange",
    shouldUnregister: false,
  });

  const [showTimePicker, setShowTimePicker] = useState(false);
  const windowHeight = Dimensions.get("window").height;
  const dialogVerticalMargin = 24;
  const dialogMaxHeight = windowHeight - dialogVerticalMargin - 60;
  const approxChrome = 140;
  const maxDialogContentHeight = Math.max(200, dialogMaxHeight - approxChrome);
  const isMobile = useAppSelector(selectIsMobile);

  const [adminSearchQuery, setAdminSearchQuery] = useState("");
  const [userSearchQuery, setUserSearchQuery] = useState("");

  const dueDate = (watch("dueDate") as Date) ?? new Date();

  // Helper function to map User to DropdownItem
  const mapUserToDropdownItem = (user: User): DropdownItem => ({
    id: user.id,
    label: `${user.firstName} ${user.lastName}`,
    subtitle: user.title,
    description: user.email,
    imageUrl: user.imageUrl,
    initials: `${user.firstName.charAt(0)}${user.lastName.charAt(0)}`,
  });

  const uniqueById = (items: DropdownItem[]) => {
    const seen = new Set<string>();
    const out: DropdownItem[] = [];
    for (const it of items) {
      if (!seen.has(it.id)) {
        seen.add(it.id);
        out.push(it);
      }
    }
    return out;
  };

  // Fetch admin users for assignee dropdown
  // Only fetch when search query has 2+ characters for better performance
  const { data: adminUsersPage } = useGetUsersQuery(
    {
      roleType: "admin",
      page: 1,
      limit: 20,
      sortBy: "name",
      sortDir: "asc" as any,
      search: adminSearchQuery.trim(),
    },
    { skip: !visible || adminSearchQuery.trim().length < 2 },
  );
  const adminUsers = adminUsersPage?.items ?? [];
  const preselectedSupervisorItems = existingSupervisors.map(
    mapUserToDropdownItem,
  );
  const adminDropdownItems = uniqueById([
    ...preselectedSupervisorItems,
    ...adminUsers.map(mapUserToDropdownItem),
  ]);

  // Fetch regular users (non-admin) for user assignment dropdown
  // Only fetch when search query has 2+ characters for better performance
  const { data: regularUsersPage } = useGetUsersQuery(
    {
      roleType: "user",
      page: 1,
      limit: 20,
      sortBy: "name",
      sortDir: "asc" as any,
      search: userSearchQuery.trim(),
    },
    { skip: !visible || userSearchQuery.trim().length < 2 },
  );
  const regularUsers = regularUsersPage?.items ?? [];
  const preselectedUserItems = existingUser
    ? [mapUserToDropdownItem(existingUser)]
    : [];
  const regularUserDropdownItems = uniqueById([
    ...preselectedUserItems,
    ...regularUsers.map(mapUserToDropdownItem),
  ]);

  const onTimeConfirm = ({
    hours,
    minutes,
  }: {
    hours: number;
    minutes: number;
  }) => {
    setShowTimePicker(false);
    const newDate = new Date(dueDate as Date);
    newDate.setHours(hours);
    newDate.setMinutes(minutes);
    setValue("dueDate", newDate, { shouldDirty: true, shouldValidate: true });
  };

  useEffect(() => {
    if (!visible) return;
    const t = todoRef.current;
    const admins = (t?.assignees ?? []).filter(
      (u) => u.role === RoleEnum.ADMIN || u.role === RoleEnum.MANAGER,
    );
    const user = (t?.assignees ?? []).find((u) => u.role === RoleEnum.USER);
    const nextDefaults: TodoFormValues = {
      id: t?.id,
      title: t?.title ?? "",
      task: t?.task ?? "",
      priority: (t?.priority ?? "LOW_PRIORITY") as PriorityStatus,
      status: (t?.status ?? "NEW") as TodoStatus,
      dueDate: t?.dueDate ? new Date(t.dueDate) : new Date(),
      assigneeIds: admins.map((u) => u.id),
      userId: user?.id,
    };
    reset(nextDefaults, { keepDefaultValues: false });
  }, [visible, reset, todo?.id, mode]);

  const submit = (vals: TodoFormValues) => {
    onSubmit({
      ...(mode === OperationMode.EDIT && todo ? { id: todo.id } : {}),
      title: vals.title.trim(),
      task: vals.task.trim(),
      priority: vals.priority as PriorityStatus,
      status: vals.status as TodoStatus,
      dueDate: (vals.dueDate as unknown as Date) ?? new Date(),
      assigneeIds: (vals.assigneeIds as string[] | undefined) ?? [],
      userId: vals.userId,
    });
  };

  const handleClose = () => {
    onClose();
  };

  return (
    <DialogContainer
      visible={visible}
      onDismiss={handleClose}
      dialogStyle={{
        alignSelf: "center",
        marginVertical: dialogVerticalMargin,
        maxHeight: dialogMaxHeight,
      }}
    >
      <Dialog.Title>
        <View className="w-full flex-row items-center justify-between">
          <View className="flex-1">
            <Text className="pr-3">
              {mode === OperationMode.ADD ? "Add Todo" : "Edit Todo"}
            </Text>
          </View>

          <View style={{ alignSelf: "flex-start" }}>
            <IconButton
              icon="close"
              size={20}
              onPress={handleClose}
              disabled={isLoading}
              accessibilityLabel="Close dialog"
              style={{ margin: 0 }}
            />
          </View>
        </View>
      </Dialog.Title>
      <Dialog.Content
        style={{ maxHeight: maxDialogContentHeight, overflow: "hidden" }}
      >
        <ScrollView nestedScrollEnabled>
          <View>
            <View
              className={isMobile ? "flex-col" : "flex-row items-stretch"}
              style={{ flex: isMobile ? undefined : 1, minHeight: 0 }}
            >
              {/* Left column */}
              <View className={isMobile ? "w-full" : "w-1/2 pr-3"}>
                <View className="mb-4">
                  <Text className="text-sm mb-1 font-medium">Title</Text>
                  <Controller
                    control={control}
                    name="title"
                    render={({ field: { onChange, value } }) => (
                      <>
                        <TextInput
                          className={`border ${
                            errors.title ? "border-highRisk" : "border-gray-300"
                          } rounded p-2 text-base bg-white`}
                          value={value}
                          onChangeText={onChange}
                          placeholder="Enter title"
                          autoCapitalize="none"
                          placeholderTextColor="#d9d9d9"
                        />
                        {errors.title ? (
                          <Text className="text-highRisk text-xs mt-1">
                            {errors.title.message as string}
                          </Text>
                        ) : null}
                      </>
                    )}
                  />
                </View>

                <View className="mb-4">
                  <Text className="text-sm mb-1 font-medium">Task</Text>
                  <Controller
                    control={control}
                    name="task"
                    render={({ field: { onChange, value } }) => (
                      <>
                        <TextInput
                          className={`border ${
                            errors.task ? "border-highRisk" : "border-gray-300"
                          } rounded p-2 text-base bg-white`}
                          value={value}
                          onChangeText={onChange}
                          placeholder="Enter task description"
                          autoCapitalize="sentences"
                          placeholderTextColor="#d9d9d9"
                          multiline
                          numberOfLines={6}
                          textAlignVertical="top"
                          style={{ minHeight: 120 }}
                        />
                        {errors.task ? (
                          <Text className="text-highRisk text-xs mt-1">
                            {errors.task.message as string}
                          </Text>
                        ) : null}
                      </>
                    )}
                  />
                </View>

                <View className="mb-4">
                  <Text className="text-sm mb-1 font-medium">Due date</Text>
                  <Controller
                    control={control}
                    name="dueDate"
                    render={({ field: { onChange, value } }) => (
                      <DatePickerInput
                        locale="en"
                        label="Select date"
                        value={value as Date}
                        onChange={(date) =>
                          onChange((date as Date) || new Date())
                        }
                        inputMode="start"
                        mode="outlined"
                      />
                    )}
                  />
                  <Button
                    onPress={() => setShowTimePicker(true)}
                    buttonColor="white"
                    buttonTextColor="black"
                    className="mt-2"
                    disabled={false}
                  >
                    {dueDate?.toLocaleTimeString([], {
                      hour: "2-digit",
                      minute: "2-digit",
                    })}
                  </Button>
                  <TimePickerModal
                    visible={showTimePicker}
                    onDismiss={() => setShowTimePicker(false)}
                    onConfirm={onTimeConfirm}
                    hours={dueDate ? dueDate.getHours() : 0}
                    minutes={dueDate ? dueDate.getMinutes() : 0}
                  />
                  {errors.dueDate ? (
                    <Text className="text-highRisk text-xs mt-1">
                      {errors.dueDate.message as string}
                    </Text>
                  ) : null}
                </View>
              </View>

              <View
                className={isMobile ? "w-full" : "w-1/2 pl-3"}
                style={{ flex: isMobile ? undefined : 1, minHeight: 0 }}
              >
                {/* Admin Assignees Dropdown */}
                <Controller
                  control={control}
                  name="assigneeIds"
                  render={({ field: { onChange, value } }) => (
                    <SearchableDropdown
                      items={adminDropdownItems}
                      selectedIds={value || []}
                      onSelectionChange={onChange}
                      label="Assign to admins or managers"
                      placeholder="Start typing to search"
                      onSearchChange={setAdminSearchQuery}
                      error={errors.assigneeIds?.message as string}
                      mode="multi"
                    />
                  )}
                />

                {/* User Assignment Dropdown */}
                <Controller
                  control={control}
                  name="userId"
                  render={({ field: { onChange, value } }) => (
                    <SearchableDropdown
                      items={regularUserDropdownItems}
                      selectedIds={value}
                      onSelectionChange={onChange}
                      label="Connect to user"
                      placeholder="Start typing to search"
                      onSearchChange={setUserSearchQuery}
                      mode="single"
                    />
                  )}
                />

                <View className="mb-4">
                  <Text className="text-sm mb-1 font-medium">Priority</Text>
                  <View className="border border-gray-300 rounded overflow-hidden">
                    <Controller
                      control={control}
                      name="priority"
                      render={({ field: { onChange, value } }) => (
                        <CustomPicker
                          selectedValue={value}
                          onValueChange={(v) => onChange(v)}
                          className="h-10"
                        >
                          <PickerItem label="Low" value="LOW_PRIORITY" />
                          <PickerItem
                            label="Moderate"
                            value="MODERATE_PRIORITY"
                          />
                          <PickerItem label="High" value="HIGH_PRIORITY" />
                        </CustomPicker>
                      )}
                    />
                  </View>
                </View>

                <View className="mb-4">
                  <Text className="text-sm mb-1 font-medium">Status</Text>
                  <View className="border border-gray-300 rounded overflow-hidden">
                    <Controller
                      control={control}
                      name="status"
                      render={({ field: { onChange, value } }) => (
                        <CustomPicker
                          selectedValue={value}
                          onValueChange={(v) => onChange(v)}
                          className="h-10"
                        >
                          <PickerItem label="New" value="NEW" />
                          <PickerItem label="In Progress" value="IN_PROGRESS" />
                          <PickerItem label="Completed" value="COMPLETED" />
                          <PickerItem label="Archived" value="ARCHIVED" />
                        </CustomPicker>
                      )}
                    />
                  </View>
                </View>
              </View>
            </View>
          </View>
        </ScrollView>
      </Dialog.Content>
      {isLoading && (
        <View
          className="absolute inset-0 bg-gray-500/30 flex items-center justify-center"
          pointerEvents="auto"
          style={{ zIndex: 1000, top: 0, right: 0, bottom: 0, left: 0 }}
        >
          <LoadingSpinner size={SizeEnum.Small} />
        </View>
      )}
      <Dialog.Actions>
        <Button
          onPress={handleSubmit(submit)}
          disabled={isLoading || !isValid || !isDirty}
          className="ml-2!"
        >
          {mode === OperationMode.ADD ? "Add" : "Edit"}
        </Button>
      </Dialog.Actions>
    </DialogContainer>
  );
};
