import React, { useCallback, useMemo } from "react";
import {
  Autocomplete,
  Box,
  Checkbox,
  Chip,
  ListSubheader,
  MenuItem,
  TextField,
  Tooltip,
} from "@mui/material";
import { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
import { useTranslation } from "react-i18next";
import differenceBy from "lodash/differenceBy";
import intersectionWith from "lodash/intersectionWith";
import { TFunction } from "i18next";
import { LeaveType } from "@/app/api/timesheets";
import dayjs, { Dayjs } from "dayjs";

interface CommonProps {
  allProjects: ProjectWithTasks[];
  assignedProjects: AssignedProject[];
  error?: boolean;
  multiple?: boolean;
  referenceDay: Dayjs;
  includeLeaves?: boolean;
  leaveTypes?: LeaveType[];
  isTimesheetAdmendment?: boolean;
}

interface SingleAutocompleteProps extends CommonProps {
  value: number | string | undefined;
  onProjectSelect: (
    projectId: number | string,
    isLeave: boolean,
  ) => void | Promise<void>;
  multiple: false;
}

interface MultiAutocompleteProps extends CommonProps {
  value: (number | undefined)[];
  onProjectSelect: (projectIds: Array<number | string>) => void;
  multiple: true;
  // No leave types for multi select (fast entry)
  includeLeaves: false;
}


type Props = SingleAutocompleteProps | MultiAutocompleteProps ;

const getGroupName = (t: TFunction, groupName: string): string => {
  switch (groupName) {
    case "non-billable":
      return t("Non-billable");
    case "assigned":
      return t("Assigned Projects");
    case "non-assigned":
      return t("Non-assigned Projects");
    case "leaves":
      return t("Leave Types");
    case "all-projects":
      return t("All projects");
    default:
      return t("Ungrouped");
  }
};

const AutocompleteProjectSelect: React.FC<Props> = ({
  allProjects,
  referenceDay,
  assignedProjects,
  value,
  onProjectSelect,
  error,
  multiple,
  leaveTypes,
  includeLeaves,
  isTimesheetAdmendment
}) => {
  const { t } = useTranslation("home");
  const allFilteredProjects = useMemo(() => {
    return allProjects.filter((p) =>
      p.actualEnd ? !referenceDay.isAfter(p.actualEnd) : true,
    );
  }, [allProjects, referenceDay]);
console.log(assignedProjects)
  const nonAssignedProjects = useMemo(() => {
    return differenceBy(allFilteredProjects, assignedProjects, "id");
  }, [allFilteredProjects, assignedProjects]);

  const options = useMemo(() => {
    return [
      {
        value: "",
        label: t("None"),
        group: "non-billable",
      },
      ...assignedProjects.map((p) => ({
        value: p.id,
        label: `${p.code} - ${p.name}`,
        group: "assigned",
      })),
      ...(includeLeaves && leaveTypes
        ? leaveTypes.map((l) => ({
            value: `leave-${l.id}`,
            label: t(l.name),
            group: "leaves",
          }))
        : []),
      ...(isTimesheetAdmendment
      ? nonAssignedProjects.map((p) => ({
        value: p.id,
        label: `${p.code} - ${p.name}`,
        group: assignedProjects.length === 0 ? "all-projects" : "non-assigned",
      }))
      : []),
    ];
  }, [assignedProjects, includeLeaves, leaveTypes, nonAssignedProjects, t]);

  const currentValue = multiple
    ? intersectionWith(options, value, (option, v) => {
        return option.value === (v ?? "");
      })
    : options.find((o) => o.value === value) || options[0];

  const onChange = useCallback(
    (
      event: React.SyntheticEvent,
      newValue:
        | { value: number | string; group: string }
        | { value: number | string }[],
    ) => {
      if (multiple) {
        const multiNewValue = newValue as { value: number | string }[];
        onProjectSelect(multiNewValue.map(({ value }) => value));
      } else {
        const singleNewVal = newValue as {
          value: number | string;
          group: string;
        };
        const isLeave = singleNewVal.group === "leaves";

        onProjectSelect(
          isLeave
            ? parseInt(singleNewVal.value.toString().split("leave-")[1])
            : singleNewVal.value,
          isLeave,
        );
      }
    },
    [onProjectSelect, multiple],
  );

  return (
    <Autocomplete
      multiple={multiple}
      noOptionsText={t("No projects")}
      disableClearable
      fullWidth
      value={currentValue}
      onChange={onChange}
      groupBy={(option) => option.group}
      getOptionLabel={(option) => option.label}
      options={options}
      disableCloseOnSelect={multiple}
      renderTags={
        multiple
          ? (value, getTagProps) =>
              value.map((option, index) => {
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                const { key, ...chipProps } = getTagProps({ index });
                return (
                  <Chip
                    {...chipProps}
                    key={`${option.value}--${option.label}`}
                    label={option.label}
                  />
                );
              })
          : undefined
      }
      renderGroup={(params) => (
        <React.Fragment key={`${params.key}-${params.group}`}>
          <ListSubheader>{getGroupName(t, params.group)}</ListSubheader>
          {params.children}
        </React.Fragment>
      )}
      renderOption={(
        params: React.HTMLAttributes<HTMLLIElement> & { key?: React.Key },
        option,
        { selected },
      ) => {
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        const { key, ...rest } = params;
        const childKey = `${option.value}--${option.label}`;

        const content = (
          <MenuItem {...rest} disableRipple value={option.value} key={childKey}>
            {multiple && (
              <Checkbox
                disableRipple
                key={`checkbox-${option.value}`}
                checked={selected}
                sx={{ transform: "translate(0)" }}
              />
            )}
            {option.label}
          </MenuItem>
        );

        const associatedProject = allProjects.find(
          (p) => p.id === option.value,
        );

        return associatedProject ? (
          <Tooltip
            key={childKey}
            placement="right"
            title={
              <Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
                <Box>
                  <Box>{t("Project Code")}</Box>
                  {associatedProject.code}
                </Box>
                <Box>
                  <Box>{t("Project Name")}</Box>
                  {associatedProject.name}
                </Box>
                {associatedProject.description && (
                  <Box>
                    <Box>{t("Project Description")}</Box>
                    {associatedProject.description}
                  </Box>
                )}
              </Box>
            }
          >
            {content}
          </Tooltip>
        ) : (
          content
        );
      }}
      renderInput={(params) => <TextField {...params} error={error} />}
    />
  );
};

export default AutocompleteProjectSelect;
