"use client";

import * as Yup from "yup";
import { Controller, useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import { useMemo, useState, useEffect } from "react";
import Card from "@mui/material/Card";
import Stack from "@mui/material/Stack";
import Scrollbar from "@/shared/components/scrollbar";
import { Box, FormControl, FormHelperText, Grid } from "@mui/material";
import InputLabel from "@mui/material/InputLabel";
import CardHeader from "@mui/material/CardHeader";
import Typography from "@mui/material/Typography";
import LoadingButton from "@mui/lab/LoadingButton";
import MenuItem from "@mui/material/MenuItem";
import Avatar from "@mui/material/Avatar";
import Chip from "@mui/material/Chip";
import { styled, Theme } from "@mui/material/styles";
import { paths } from "@/routes/paths";
import { useBoolean, useRouter } from "@/hooks";
import { useResponsive } from "@/hooks";
import { SnackbarProvider, useSnackbar } from "@/components/snackbar";
import FormProvider, {
  RHFTextField,
  RHFAutocomplete,
  RHFSelect,
  RHFRadioGroup,
  RHFEditor,
} from "@/shared/components/hook-form";
import { ITaskItem, ICollaborator, IManager } from "@/contexts/types/tasks";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DatePicker } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import TaskDetailsPriority from "./task-details-priority";
import { Select, Tooltip } from "@mui/material";
import Iconify from "@/shared/components/iconify";
import AIDialog from "../add-project/dialog-chat-AI";
import axios, { axiosInstance, endpoints } from "@/utils/axios";
import { createTask, useGetCollaboratorsOfProject } from "@/shared/api/task";
import { IProject, Project } from "@/contexts/types/Project";
import { IKanbanColumn } from "@/shared/types/kanban";
import { generateToken } from "@/utils/firebase";
import { INotif } from '@/shared/types/notif';
import { sendNotificationToUserAfterAssigningTask, sendNotificationToUserAfterInvoiceCreation } from '@/shared/api/notif';
import { useSearchParams } from 'next/navigation';

// ----------------------------------------------------------------------

const StyledLabel = styled("span")(({ theme }) => ({
  ...theme.typography.caption,
  width: 100,
  flexShrink: 0,
  color: theme.palette.text.secondary,
  fontWeight: theme.typography.fontWeightSemiBold,
}));

// ----------------------------------------------------------------------

type Props = {
  currentTask?: ITaskItem;
  onChangePriority: (newValue: string) => void;
};

export default function TaskNewEditForm({ currentTask }: Props) {
  const router = useRouter();
  const share = useBoolean();
  const mdUp = useResponsive("up", "md");
  const { enqueueSnackbar } = useSnackbar();
  const searchParams = useSearchParams();

  // State declarations
  const [projects, setProjects] = useState<Project[]>([]);
  const [selectedStatus, setSelectedStatus] = useState<IKanbanColumn | null>(
    null
  );
  const [statuses, setStatuses] = useState<IKanbanColumn[]>([]);
  const [managers, setManagers] = useState<IManager[]>([]);
  const [selectedProject, setSelectedProject] = useState<Project | null>(null);
  const [collaborators, setCollaborators] = useState<ICollaborator[]>([]);
  const token = localStorage.getItem("token");
  const TASK_TYPES = [
    { value: "bug", label: "Bug" },
    { value: "feature", label: "Feature" },
  ];
  const STATUSES = [
    { id: 1, name: "TO DO" },
    { id: 2, name: "IN PROGRESS" },
    { id: 3, name: "DONE" },
  ];
  const UserMicroserviceEndpoints = {
    fetchCollaboratorsByProject: (
      collaboratorsIds: number[],
      agencyId: number
    ) =>
      `${
        process.env.NEXT_PUBLIC_GATEWAY_API
      }/api/user/collaborators?collaboratorsIds=${collaboratorsIds.join(
        ","
      )}&agencyId=${agencyId}`,
    fetchManagersByProject: (managersId: number, agencyId: number) =>
      `${process.env.NEXT_PUBLIC_GATEWAY_API}/api/user/managers?managersId=${managersId}&agencyId=${agencyId}`,
  };

  useEffect(() => {
    if (selectedProject) {
      const { collaboratorsIds, agencyId } = selectedProject;

      if (collaboratorsIds && collaboratorsIds.length > 0 && agencyId) {
        fetchCollaboratorsFromUserMicroservice(collaboratorsIds, agencyId);
      }
    }
  }, [selectedProject]);

  // Form schema and default values
  const TaskSchema = Yup.object().shape({
    name: Yup.string().required("Name is required"),
    project: Yup.object()
      .shape({
        id: Yup.number().required("id is required"),
        name: Yup.string().required("name is required"),
      })
      .required("Project is required"),
    // Optional fields
    endDate: Yup.mixed<any>(),
    collaboratorids: Yup.array(),
    priority: Yup.string(),
    type: Yup.string(),
    managerId: Yup.number(),
    point: Yup.number().default(0),
    column: Yup.object().shape({
      id: Yup.number(),
      name: Yup.string(),
      taskIds: Yup.array().of(Yup.number()),
    }),
    attachments: Yup.array(),
    description: Yup.string(),
    status: Yup.string(),
  });

  const defaultValues = useMemo(
    () => ({
      name: currentTask?.name || "",
      endDate: currentTask?.endDate || new Date(),
      description: currentTask?.description || "",
      collaboratorids: currentTask?.collaboratorIds || [],
      priority: currentTask?.priority || "MEDIUM",
      type: currentTask?.type || "feature",
      column: currentTask?.column || {
        id: 1,
        name: "To Do",
      },
      status: currentTask?.status || "TO DO",
      attachments: currentTask?.attachments || [],
      managerId: currentTask?.managerId || 0,
      project: currentTask?.project || {
        id: currentTask?.project?.id,
        name: currentTask?.project?.name,
      },
      point: currentTask?.point || 0,
    }),
    [currentTask]
  );

  // Initialize form
  const methods = useForm({
    resolver: yupResolver(TaskSchema),
    defaultValues: {
      name: "",
      description: "",
      collaboratorids: [],
      priority: "MEDIUM",
      point: 0,
    },
  });

  // Destructure methods AFTER its declaration
  const {
    reset,
    control,
    watch,
    setValue,
    handleSubmit,
    formState: { isSubmitting },
  } = methods;

  // Now we can use the useEffect with setValue
  useEffect(() => {
    const projectId = searchParams.get('projectId');
    
    if (projectId && projects.length > 0) {
      const selectedProject = projects.find(p => p.id === Number(projectId));
      if (selectedProject) {
        setSelectedProject(selectedProject);
        setValue('project', selectedProject);
      }
    }
  }, [projects, searchParams, setValue]);

  const fetchCollaboratorsFromUserMicroservice = async (
    collaboratorsIds: number[],
    agencyId: number
  ) => {
    try {
      const response = await axiosInstance.get(
        UserMicroserviceEndpoints.fetchCollaboratorsByProject(
          collaboratorsIds,
          agencyId
        ),
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );
      setCollaborators(response.data || []);
      console.log("Collaborators fetched:", response.data);
    } catch (error) {
      console.error("Error fetching collaborators:", error);
    }
  };

  const fetchManagerFromUserMicroservice = async (
    responsibleId: number,
    agencyId: number
  ) => {
    try {
      const response = await axiosInstance.get(
        `${process.env.NEXT_PUBLIC_GATEWAY_API}/api/user/managers?managersId=${responsibleId}&agencyId=${agencyId}`,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );
      setManagers(response.data ? [response.data] : []); // Fallback to empty array if response.data is undefined
      console.log("Manager fetched:", response.data);
    } catch (error) {
      console.error("Error fetching manager:", error);
    }
  };

  useEffect(() => {
    if (selectedProject) {
      const { responsibleId, agencyId } = selectedProject;
      if (responsibleId && agencyId) {
        fetchManagerFromUserMicroservice(responsibleId, agencyId);
      }
    }
  }, [selectedProject]);
  const agencyId = Number(localStorage.getItem("selectedAgency"));
  useEffect(() => {
    const fetchProjects = async () => {
      try {
        const response = await axios.get(
          `${endpoints.project.list}/${agencyId}`
        );
        setProjects(response.data);
      } catch (error) {
        console.error("Error fetching projects:", error);
      }
    };
    fetchProjects();
  }, []);

  useEffect(() => {
    if (selectedProject) {
      const { responsibleId, agencyId } = selectedProject;

      if (responsibleId && agencyId) {
        fetchManagerFromUserMicroservice(responsibleId, agencyId);
      }
    }
  }, [selectedProject]);

  const [priority, setPriority] = useState(defaultValues.priority);

  const values = watch();

  useEffect(() => {
    if (currentTask) {
      reset(defaultValues);
    }
  }, [currentTask, defaultValues, reset]);

  const [isProcessingImages, setIsProcessingImages] = useState(false);

  // Define styles at the beginning of the component
  const descriptionStyles = {
    '& img': {
      maxWidth: '100%',
      height: 'auto',
      margin: '10px 0',
      borderRadius: 1,
      boxShadow: (theme: Theme) => theme.shadows[1],
    },
  };

  // Define `onSubmit` without wrapping it in `handleSubmit`
  const onSubmit = async (data: any) => {
    try {
      setIsProcessingImages(true);
      
      const selectedStatus = STATUSES.find(s => s.id.toString() === data.status)?.name || "TO DO";
      
      const submissionData = {
        ...data,
        type: data?.type?.toUpperCase() || "FEATURE",
        status: selectedStatus, 
        projectId: selectedProject?.id,
        priority: data.priority || "MEDIUM",
        collaboratorIds: data.collaboratorids
          ?.map((collab: { id: number }) => collab.id)
          .filter(Boolean) ?? [],
        managerId: data.managerId || null,
        endDate: data.endDate ? data.endDate.toISOString() : new Date(),
      };

      delete submissionData.collaboratorids;

      const apiUrl = `${process.env.NEXT_PUBLIC_GATEWAY_API}/api/projects/api/tasks/add`;

      const response = await axios.post(apiUrl, submissionData, {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });

      if (response.status === 200) {
        // Send notifications to assigned collaborators
        const firebaseToken = await generateToken();
        
        if (firebaseToken) {
          // Get the selected collaborator objects from the collaborators state
          const selectedCollaborators = collaborators.filter(collab => 
            submissionData.collaboratorIds.includes(collab.id)
          );

          // Send notification for each collaborator
          for (const collaborator of selectedCollaborators) {
            try {
              // Fetch collaborator details to get email
              const response = await axiosInstance.get(
                `${process.env.NEXT_PUBLIC_GATEWAY_API}/api/user/accountagency/id`,
                {
                  params: { Id: collaborator.id }
                }
              );
              const collaboratorDetails = response.data;

              if (collaboratorDetails?.user?.email) {
                const notificationData: INotif = {
                  firebaseToken,
                  email: collaboratorDetails.user.email,
                };
                
                await sendNotificationToUserAfterAssigningTask(notificationData);
              }
            } catch (error) {
              console.error(`Error fetching collaborator details:`, error);
            }
          }
        } else {
          console.warn('Failed to generate Firebase token');
        }

        reset();
        router.push(paths.dashboard.tasks.all_tasks);
        enqueueSnackbar(currentTask ? "Update success!" : "Create success!");
      } else {
        enqueueSnackbar(
          currentTask ? "Failed to update task!" : "Failed to create task!",
          { variant: "error" }
        );
      }
    } catch (error) {
      console.error('Error creating/updating task:', error);
      enqueueSnackbar("An error occurred. Please try again later.", {
        variant: "error",
      });
    } finally {
      setIsProcessingImages(false);
    }
  };

  // For handling description updates in existing tasks
  const handleDescriptionGenerated = async (description: string) => {
    try {
      if (description.includes('base64')) {
        setIsProcessingImages(true);
      }
      
      setValue('description', description, { 
        shouldValidate: true,
        shouldDirty: true 
      });
    } finally {
      setIsProcessingImages(false);
    }
  };

  const renderDetails = (
    <Grid container spacing={2} alignItems="stretch">
      <Grid item xs={12} md={6}>
        <Card>
          {!mdUp && <CardHeader title="Part 1" />}
          <Stack spacing={3} sx={{ p: 3 }}>
            <RHFTextField name="name" label="Task Name" />
            <Controller
              name="type"
              control={control}
              render={({ field }) => (
                <RHFSelect {...field} label="Task Type">
                  {TASK_TYPES.map((option) => (
                    <MenuItem key={option.value} value={option.value}>
                      {option.label}
                    </MenuItem>
                  ))}
                </RHFSelect>
              )}
            />

            <Controller
              name="project"
              control={control}
              render={({ field }) => (
                <RHFSelect
                  {...field}
                  fullWidth
                  label="Select a Project"
                  value={selectedProject?.id || field.value?.id || ''}
                  onChange={(e) => {
                    const projectId = Number(e.target.value);
                    const selectedProject = projects.find(
                      (p) => p.id === projectId
                    );
                    setSelectedProject(selectedProject || null);
                    field.onChange(selectedProject);
                  }}
                >
                  {(projects || []).map((project) => (
                    <MenuItem key={project.id} value={project.id}>
                      {project.name}
                    </MenuItem>
                  ))}
                </RHFSelect>
              )}
            />

            <Stack spacing={1.5}>
              <Typography variant="subtitle2">Description</Typography>
              <RHFEditor 
                simple 
                name="description" 
                sx={descriptionStyles}
              />
            </Stack>

            <Tooltip title="Use AI to generate a description">
              <Iconify
                icon="fluent-emoji:magic-wand"
                onClick={share.onTrue}
                sx={{
                  width: 27,
                  height: 27,
                  color: "grey",
                  bottom: 10,
                  right: 4,
                  ml: 1,
                }}
              />
            </Tooltip>
          </Stack>
        </Card>
      </Grid>

      <Grid item xs={12} md={6}>
        <Card>
          {!mdUp && <CardHeader title="Part 2" />}
          <Stack spacing={3} sx={{ p: 3 }}>
            <Controller
              name="endDate"
              control={control}
              render={({ field, fieldState: { error } }) => (
                <DatePicker
                  label="Due Date"
                  value={field.value}
                  onChange={(newValue: any) => {
                    field.onChange(newValue);
                  }}
                  slotProps={{
                    textField: {
                      fullWidth: true,
                      error: !!error,
                      helperText: error?.message,
                    },
                  }}
                />
              )}
            />

            <Controller
              control={control}
              name="managerId"
              render={({
                field: { onChange, value },
                fieldState: { error },
              }) => (
                <FormControl fullWidth error={!!error}>
                  <InputLabel>Select a Manager</InputLabel>
                  <Select
                    label="Select a Manager"
                    value={value ?? ""}
                    onChange={(event) => {
                      const selectedManagerId = event.target.value;
                      onChange(selectedManagerId);
                    }}
                  >
                    <MenuItem value="" disabled>
                      Select a Manager
                    </MenuItem>
                    {managers.map((manager) => (
                      <MenuItem key={manager.id} value={manager.id}>
                        <Avatar
                          alt={`${manager.user?.firstName || "Unknown"} ${
                            manager.user?.lastName || ""
                          }`}
                          sx={{
                            width: 40,
                            height: 40,
                            flexShrink: 0,
                            marginRight: 1,
                          }}
                        >
                          {manager.user?.firstName?.charAt(0) || ""}
                          {manager.user?.lastName?.charAt(0) || ""}
                        </Avatar>
                        {manager.user
                          ? `${manager.user.firstName} ${manager.user.lastName}`
                          : "Unknown Manager"}
                      </MenuItem>
                    ))}
                  </Select>
                  {error && <FormHelperText>{error.message}</FormHelperText>}
                </FormControl>
              )}
            />

            <RHFAutocomplete
              multiple
              name="collaboratorids"
              placeholder="+ Add Collaborators"
              options={Array.isArray(collaborators) ? collaborators : []} // Ensure options is an array
              value={values.collaboratorids}
              getOptionLabel={(option) =>
                option.user
                  ? `${option.user.firstName || ""} ${
                      option.user.lastName || ""
                    }`
                  : "Unknown Collaborator"
              }
              isOptionEqualToValue={(option, value) => option.id === value.id}
              onChange={(event, newValue) =>
                setValue("collaboratorids", newValue)
              }
              renderOption={(props, collaborator) => (
                <li {...props} key={collaborator.id}>
                  <Avatar
                    alt={`${collaborator.user?.firstName || "Unknown"} ${
                      collaborator.user?.lastName || ""
                    }`}
                    sx={{ width: 40, height: 40, marginRight: 1 }}
                  >
                    {collaborator.user?.firstName?.charAt(0) || ""}
                    {collaborator.user?.lastName?.charAt(0) || ""}
                  </Avatar>
                  {collaborator.user
                    ? `${collaborator.user.firstName} ${collaborator.user.lastName}`
                    : "Unknown Collaborator"}
                </li>
              )}
              renderTags={(selected, getTagProps) =>
                selected.map((collaborator, index) => (
                  <Chip
                    {...getTagProps({ index })}
                    key={collaborator.id}
                    size="small"
                    label={
                      collaborator.user
                        ? `${collaborator.user.firstName} ${collaborator.user.lastName}`
                        : "Unknown Collaborator"
                    }
                    avatar={<Avatar alt={collaborator.user?.firstName} />}
                  />
                ))
              }
            />

            <Stack direction="row" alignItems="center">
              <StyledLabel>Priority</StyledLabel>
              <Controller
                name="priority"
                control={control}
                render={({ field }) => (
                  <TaskDetailsPriority
                    priority={priority}
                    onChangePriority={(newValue: string) => {
                      field.onChange(newValue);
                      setPriority(newValue);
                    }}
                  />
                )}
              />
            </Stack>

            <Controller
              name="status"
              control={control}
              defaultValue="1" // Default to "TO DO"
              render={({ field }) => (
                <RHFSelect
                  {...field}
                  fullWidth
                  label="Select a Status"
                  value={field.value?.toString()}
                  onChange={(e) => {
                    const selectedStatus = e.target.value;
                    field.onChange(selectedStatus);
                  }}
                >
                  {STATUSES.map((status) => (
                    <MenuItem key={status.id} value={status.id.toString()}>
                      {status.name}
                    </MenuItem>
                  ))}
                </RHFSelect>
              )}
            />

            <RHFTextField
              name="point"
              label="Mark"
              placeholder="0"
              type="number"
              InputLabelProps={{ shrink: true }}
            />
          </Stack>
        </Card>
      </Grid>
    </Grid>
  );

  const renderActions = (
    <>
      {mdUp && <Grid item md={4} />}
      <Grid item xs={12} md={12} sx={{ mt: 2 }}>
        <LoadingButton
          type="submit"
          variant="contained"
          size="large"
          loading={isSubmitting || isProcessingImages}
        >
          {currentTask ? "Save Changes" : "Create Task"}
        </LoadingButton>
      </Grid>
    </>
  );

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
        <Grid container spacing={3}>
          <Grid xs={12} md={12}>
            {renderDetails}
            {renderActions}
          </Grid>
        </Grid>
      </FormProvider>

      <AIDialog 
        open={share.value} 
        onClose={share.onFalse}
        onDescriptionGenerated={handleDescriptionGenerated}
        type="task"
      />
    </LocalizationProvider>
  );
}
