"use client";

import AutorenewIcon from "@mui/icons-material/Autorenew";
import DoneIcon from "@mui/icons-material/Done";
import Check from "@mui/icons-material/Check";
import Close from "@mui/icons-material/Close";
import Button, { ButtonProps } from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import Tab from "@mui/material/Tab";
import Tabs, { TabsProps } from "@mui/material/Tabs";
import { useRouter, useSearchParams } from "next/navigation";
import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { useTranslation } from "react-i18next";
import ProjectClientDetails from "./ProjectClientDetails";
import TaskSetup from "./TaskSetup";
import StaffAllocation from "./StaffAllocation";
import Milestone from "./Milestone";
import { Task, TaskTemplate } from "@/app/api/tasks";
import {
  FieldErrors,
  FormProvider,
  SubmitErrorHandler,
  SubmitHandler,
  useForm,
} from "react-hook-form";
import {
  CreateProjectInputs,
  deleteProject,
  saveProject,
} from "@/app/api/projects/actions";
import { Delete, EditNote, Error, PlayArrow } from "@mui/icons-material";
import {
  BuildingType,
  ContractType,
  FundingType,
  LocationType,
  MainProject,
  ProjectCategory,
  ServiceType,
  WorkNature,
} from "@/app/api/projects";
import { StaffResult } from "@/app/api/staff";
import { Box, Grid, Typography } from "@mui/material";
import { Grade } from "@/app/api/grades";
import { Customer, CustomerType, Subsidiary } from "@/app/api/customer";
import { isEmpty } from "lodash";
import {
  deleteDialog,
  errorDialog,
  submitDialog,
  submitDialogWithWarning,
  successDialog,
} from "../Swal/CustomAlerts";
import dayjs from "dayjs";
import { DELETE_PROJECT } from "@/middleware";
import { OUTPUT_DATE_FORMAT, sumMoney } from "@/app/utils/formatUtil";
import { deleteDraft, loadDraft, saveToLocalStorage } from "@/app/utils/draftUtils";

export interface Props {
  isEditMode: boolean;
  isCopyMode: boolean;
  draftId?: number;
  isSubProject: boolean;
  mainProjects?: MainProject[];
  defaultInputs?: CreateProjectInputs;
  allTasks: Task[];
  projectCategories: ProjectCategory[];
  taskTemplates: TaskTemplate[];
  teamLeads: StaffResult[];
  allCustomers: Customer[];
  allSubsidiaries: Subsidiary[];
  fundingTypes: FundingType[];
  serviceTypes: ServiceType[];
  contractTypes: ContractType[];
  locationTypes: LocationType[];
  buildingTypes: BuildingType[];
  workNatures: WorkNature[];
  allStaffs: StaffResult[];
  customerTypes: CustomerType[];
  grades: Grade[];
  abilities: string[];
}

const hasErrorsInTab = (
  tabIndex: number,
  errors: FieldErrors<CreateProjectInputs>,
) => {
  switch (tabIndex) {
    case 0:
      return (
        errors.projectName ||
        errors.projectDescription ||
        errors.clientId ||
        errors.projectCode || 
        errors.projectPlanStart || 
        errors.projectPlanEnd
      );
    case 2:
      return (
        errors.totalManhour ||
        errors.manhourPercentageByGrade ||
        errors.taskGroups ||
        errors.ratePerManhour
      );
    case 3:
      return errors.milestones;
    default:
      false;
  }
};

const CreateProject: React.FC<Props> = ({
  isEditMode,
  isCopyMode,
  draftId: initDraftId,
  isSubProject,
  mainProjects,
  defaultInputs,
  allTasks,
  projectCategories,
  taskTemplates,
  teamLeads,
  grades,
  allCustomers,
  allSubsidiaries,
  contractTypes,
  fundingTypes,
  locationTypes,
  serviceTypes,
  buildingTypes,
  workNatures,
  allStaffs,
  customerTypes,
  abilities,
}) => {
  const [draftId, setDraftId] = useState(initDraftId)
  const [serverError, setServerError] = useState("");
  const [tabIndex, setTabIndex] = useState(0);
  const { t } = useTranslation();
  const router = useRouter();

  const formProps = useForm<CreateProjectInputs>({
    defaultValues: {
      taskGroups: {},
      allocatedStaffIds: [],
      milestones: {},
      totalManhour: 0,
      taskTemplateId: "All",
      projectName:
        mainProjects !== undefined ? mainProjects[0].projectName : undefined,
      projectDescription:
        mainProjects !== undefined
          ? mainProjects[0].projectDescription
          : undefined,
      expectedProjectFee:
        mainProjects !== undefined
          ? mainProjects[0].expectedProjectFee
          : undefined,
      subContractFee:
        mainProjects !== undefined ? mainProjects[0].subContractFee : undefined,
      clientId: allCustomers !== undefined ? allCustomers[0].id : undefined,
      ratePerManhour: 250,
      ...defaultInputs,

      // manhourPercentageByGrade should have a sensible default
      manhourPercentageByGrade: isEmpty(defaultInputs?.manhourPercentageByGrade)
        ? grades.reduce((acc, grade) => {
            return { ...acc, [grade.id]: 100 / grades.length };
          }, {})
        : defaultInputs?.manhourPercentageByGrade,
    },
  });

  const projectName = formProps.watch("projectName");
  const projectDeleted = formProps.watch("projectDeleted");
  const projectStatus = formProps.watch("projectStatus") || "";

  const defaultBtn = {
    buttonName: "submit",
    title: t("Do you want to submit?"),
    confirmButtonText: t("Submit"),
    successTitle: t("Submit Success"),
    errorTitle: t("Submit Fail"),
  };
  const buttonData = useMemo<{
    buttonName: string;
    title: string;
    confirmButtonText: string;
    successTitle: string;
    errorTitle: string;
    buttonText: string;
    buttonIcon: React.ReactNode;
    buttonColor: ButtonProps["color"];
  }>(() => {
    //Button Parameters//
    switch (projectStatus.toLowerCase()) {
      case "pending to start":
        return {
          buttonName: "start",
          title: t("Do you want to start?"),
          confirmButtonText: t("Start"),
          successTitle: t("Start Success"),
          errorTitle: t("Start Fail"),
          buttonText: t("Start Project"),
          buttonIcon: <PlayArrow />,
          buttonColor: "success",
        };
      case "on-going":
        return {
          buttonName: "complete",
          title: t("Do you want to complete?"),
          confirmButtonText: t("Complete"),
          successTitle: t("Complete Success"),
          errorTitle: t("Complete Fail"),
          buttonText: t("Complete Project"),
          buttonIcon: <DoneIcon />,
          buttonColor: "info",
        };
      case "completed":
        return {
          buttonName: "reopen",
          title: t("Do you want to reopen?"),
          confirmButtonText: t("Reopen"),
          successTitle: t("Reopen Success"),
          errorTitle: t("Reopen Fail"),
          buttonText: t("Reopen Project"),
          buttonIcon: <AutorenewIcon />,
          buttonColor: "secondary",
        };
      default:
        return {
          buttonName: "submit",
          title: t("Do you want to submit?"),
          confirmButtonText: t("Submit"),
          successTitle: t("Submit Success"),
          errorTitle: t("Submit Fail"),
          buttonText: t("Submit Project"),
          buttonIcon: <Check />,
          buttonColor: "success",
        };
    }
  }, [projectStatus, t]);

  const handleCancel = () => {
    router.replace("/projects");
  };

  const handleDelete = () => {
    deleteDialog(async () => {
      await deleteProject(formProps.getValues("projectId")!);

      const clickSuccessDialog = await successDialog("Delete Success", t);

      if (clickSuccessDialog) {
        router.replace("/projects");
      }
    }, t);
  };

  const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>(
    (_e, newValue) => {
      setTabIndex(newValue);
    },
    [],
  );

  const onSubmit = useCallback<SubmitHandler<CreateProjectInputs>>(
    async (data, event) => {
      try {
        // console.log(data);

        // detect errors
        let hasErrors = false;

        if(
          !data.projectPlanStart || !data.projectPlanEnd
        ){
          formProps.setError("projectPlanStart", {
            message: "projectPlanStart is not valid",
            type: "required",
          });
          setTabIndex(0);
          hasErrors = true;
        }

        // Tab - Staff Allocation and Resource
        if (
          data.totalManhour === null ||
          data.totalManhour <= 0 ||
          Number.isNaN(data.totalManhour)
        ) {
          formProps.setError("totalManhour", {
            message: "totalManhour value is not valid",
            type: "required",
          });
          setTabIndex(2);
          hasErrors = true;
        }

        if (
          data.ratePerManhour === null ||
          data.ratePerManhour <= 0 ||
          Number.isNaN(data.ratePerManhour)
        ) {
          formProps.setError("ratePerManhour", {
            message: "ratePerManhour value is not valid",
            type: "required",
          });
          setTabIndex(2);
          hasErrors = true;
        }

        const manhourPercentageByGradeKeys = Object.keys(
          data.manhourPercentageByGrade,
        );
        if (
          manhourPercentageByGradeKeys.filter(
            (k) => data.manhourPercentageByGrade[k as any] < 0,
          ).length > 0 ||
          manhourPercentageByGradeKeys.reduce(
            (acc, value) => acc + data.manhourPercentageByGrade[value as any],
            0,
          ) !== 100
        ) {
          formProps.setError("manhourPercentageByGrade", {
            message: "manhourPercentageByGrade value is not valid",
            type: "invalid",
          });
          setTabIndex(2);
          hasErrors = true;
        }

        const taskGroupKeys = Object.keys(data.taskGroups);
        if (
          taskGroupKeys.filter(
            (k) => data.taskGroups[k as any].percentAllocation < 0,
          ).length > 0 ||
          taskGroupKeys.reduce(
            (acc, value) =>
              acc + data.taskGroups[value as any].percentAllocation,
            0,
          ) !== 100
        ) {
          formProps.setError("taskGroups", {
            message: "Task Groups value is not invalid",
            type: "invalid",
          });
          setTabIndex(2);
          hasErrors = true;
        }

        // Tab - Milestone
        let projectTotal = 0;
        const milestonesKeys = Object.keys(data.milestones).filter((key) =>
          taskGroupKeys.includes(key),
        );
        milestonesKeys
          .filter((key) => Object.keys(data.taskGroups).includes(key))
          .forEach((key) => {
            const { startDate, endDate, payments } =
              data.milestones[parseFloat(key)];
              if (
                  !Boolean(startDate) ||
                  startDate === "Invalid Date" ||
                  !Boolean(endDate) ||
                  endDate === "Invalid Date"
                ){
                  data.milestones[parseFloat(key)].startDate = null
                  data.milestones[parseFloat(key)].endDate = null
                }
            /* 
            unused code for checking the stage start date and end date
            if (
              !Boolean(startDate) ||
              startDate === "Invalid Date" ||
              !Boolean(endDate) ||
              endDate === "Invalid Date" ||
              new Date(startDate) > new Date(endDate)
            ) {
              formProps.setError("milestones", {
                message: "milestones is not valid",
                type: "invalid",
              });
              setTabIndex(3);
              hasErrors = true;
            }

            unused code for bulk add milestone payment
            projectTotal += payments.reduce(
              (acc, payment) => acc + payment.amount,
              0,
            );
            **/

            projectTotal += payments.reduce(
              (acc, p) => sumMoney(acc, p.amount),
              0,
            );

            
          });
          // console.log(projectTotal)
          console.log(milestonesKeys)

        if (
          projectTotal !== data.expectedProjectFee 
          // || milestonesKeys.length !== taskGroupKeys.length
        ) {
          formProps.setError("milestones", {
            message: "milestones is not valid",
            type: "invalid",
          });
          setTabIndex(3);
          hasErrors = true;
        }

        if (hasErrors) return false;
        // save project
        setServerError("");

        const buttonName = (event?.nativeEvent as any).submitter.name;

        const handleSubmit = async () => {
          if (buttonName === "start") {
            data.projectActualStart = dayjs().format("YYYY-MM-DD");
          } else if (buttonName === "complete") {
            data.projectActualEnd = dayjs().format("YYYY-MM-DD");
          }
          data.taskTemplateId =
            data.taskTemplateId === "All" ? undefined : data.taskTemplateId;
          const response = await saveProject(data);

          if (
            response.id > 0 &&
            response.message?.toLowerCase() === "success" &&
            response.errorPosition === null
          ) {
            successDialog(
              buttonName === "submit"
                ? defaultBtn.successTitle
                : buttonData.successTitle,
              t,
            ).then(() => {
              if (draftId) {
                deleteDraft(draftId);
              }
              router.replace("/projects");
            });
          } else {
            errorDialog(
              response.message ??
                (buttonName === "submit"
                  ? defaultBtn.errorTitle
                  : buttonData.errorTitle),
              t,
            ).then(() => {
              if (
                response.errorPosition !== null &&
                response.errorPosition === "projectCode"
              ) {
                formProps.setError("projectCode", {
                  message: response.message,
                  type: "invalid",
                });
                setTabIndex(0);
              }

              return false;
            });
          }
        };

        if (buttonName === "complete") {
          submitDialogWithWarning(handleSubmit, t, {
            title: buttonData.title,
            confirmButtonText: buttonData.confirmButtonText,
            text: "<b style='color:red'>Completing project will restrict any further changes to the project, are you sure to proceed?</b>",
          });
        } else if (buttonName === "submit") {
          submitDialog(handleSubmit, t, {
            title: defaultBtn.title,
            confirmButtonText: defaultBtn.confirmButtonText,
          });
        } else {
          submitDialog(handleSubmit, t, {
            title: buttonData.title,
            confirmButtonText: buttonData.confirmButtonText,
          });
        }
      } catch (e) {
        setServerError(t("An error has occurred. Please try again later."));
      }
    },
    [router, t, draftId],
  );

  const onSubmitError = useCallback<SubmitErrorHandler<CreateProjectInputs>>(
    (errors) => {
      console.log(errors);
      // Set the tab so that the focus will go there
      if (
        errors.projectName ||
        errors.projectDescription ||
        errors.projectCode ||
        errors.clientId || 
        errors.projectPlanStart ||
        errors.projectPlanEnd
      ) {
        setTabIndex(0);
      } else if (
        errors.totalManhour ||
        errors.manhourPercentageByGrade ||
        errors.taskGroups ||
        errors.ratePerManhour
      ) {
        setTabIndex(2);
      } else if (errors.milestones) {
        setTabIndex(3);
      }
    },
    [],
  );

  const errors = formProps.formState.errors;

  // auto calculate the total project manhour
  const expectedProjectFee = formProps.watch("expectedProjectFee");
  const ratePerManhour = formProps.watch("ratePerManhour");
  const totalManhour = formProps.watch("totalManhour");
  const subContractFee = formProps.watch("subContractFee");
  const firstLoadedRef = useRef(false);
  useEffect(() => {
    if (
      firstLoadedRef.current &&
      expectedProjectFee > 0 &&
      ratePerManhour > 0
    ) {
      formProps.setValue(
        "totalManhour",
        Math.ceil((expectedProjectFee - (subContractFee ?? 0)) / ratePerManhour),
      );
    } else {
      firstLoadedRef.current = true;
    }
  }, [expectedProjectFee, subContractFee, ratePerManhour]);

  useEffect(() => {
    if (
      expectedProjectFee > 0 &&
      ratePerManhour > 0 &&
      (totalManhour === null || Number.isNaN(totalManhour) || totalManhour <= 0)
    ) {
      formProps.setValue(
        "totalManhour",
        Math.ceil((expectedProjectFee - (subContractFee ?? 0)) / ratePerManhour),
      );
    }
  }, [totalManhour]);

  const loading = isEditMode || isCopyMode ? !Boolean(projectName) : false;

  const submitDisabled =
    loading ||
    projectDeleted === true ||
    projectStatus.toLowerCase() === "deleted" ||
    // !!formProps.getValues("projectActualStart") &&
    !!(projectStatus.toLowerCase() === "completed");

  useEffect(() => {
    const draftInputs = draftId ? loadDraft(draftId) : undefined;
    formProps.reset(draftInputs);
  }, [draftId, formProps]);

  const saveDraft = useCallback(async () => {
    const currentTimestamp = Date.now()
    console.log(currentTimestamp)

    saveToLocalStorage(draftId || currentTimestamp, formProps.getValues());
    
    const success = await successDialog("Save Success", t)

    if (success && !draftId) {
      setDraftId(currentTimestamp)
    }
    // router.replace("/projects");
  }, [draftId, formProps, router]);

  const handleDeleteDraft = useCallback(() => {
    deleteDialog(async () => {
      deleteDraft(Number(draftId));

      const clickSuccessDialog = await successDialog("Delete Success", t);

      if (clickSuccessDialog) {
        router.replace("/projects");
      }
    }, t);
  }, [draftId, router]);

  // Auto click the button
  const buttonRef = useRef<HTMLButtonElement>(null)
  const searchParams = useSearchParams()

  useEffect(() => {
    if (buttonRef) {
      const autoClickButton = searchParams.get("autoClick")
      // const autoClickList = ["start", "complete", "reopen"]
  
      if(autoClickButton && autoClickButton === "true") {
        buttonRef.current?.click()
      }
    }
  }, [buttonRef])

  return (
    <>
      <FormProvider {...formProps}>
        <Stack
          spacing={2}
          component="form"
          onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
        >
          {isEditMode &&
            !(formProps.getValues("projectDeleted") === true) &&
            !loading && (
              <Grid>
                <Typography mb={2} variant="h4">
                  {t("Edit Project")}: {`<${defaultInputs?.projectCode}>`}
                </Typography>
                {(defaultInputs?.projectActualEnd ||
                  defaultInputs?.projectActualStart) && (
                  <Stack mb={2}>
                    {defaultInputs?.projectActualStart && (
                      <Typography variant="caption">
                        {t("Project Start Date: {{date}}", {
                          date: dayjs(defaultInputs.projectActualStart).format(
                            OUTPUT_DATE_FORMAT,
                          ),
                        })}
                      </Typography>
                    )}
                    {defaultInputs?.projectActualEnd && (
                      <Typography variant="caption">
                        {t("Project End Date: {{date}}", {
                          date: dayjs(defaultInputs.projectActualEnd).format(
                            OUTPUT_DATE_FORMAT,
                          ),
                        })}
                      </Typography>
                    )}
                  </Stack>
                )}
                <Stack direction="row" gap={1}>
                  {/* {!formProps.getValues("projectActualStart") && ( */}
                  <Button
                    ref={buttonRef}
                    name={buttonData.buttonName}
                    type="submit"
                    variant="contained"
                    startIcon={buttonData.buttonIcon}
                    color={buttonData.buttonColor}
                  >
                    {t(buttonData.buttonText)}
                  </Button>
                  {!(
                    // formProps.getValues("projectActualStart") &&
                    // formProps.getValues("projectActualEnd")
                    (
                      projectStatus.toLowerCase() === "completed" ||
                      projectStatus.toLowerCase() === "deleted"
                    )
                  ) &&
                    abilities.includes(DELETE_PROJECT) && (
                      <Button
                        variant="outlined"
                        startIcon={<Delete />}
                        color="error"
                        onClick={handleDelete}
                      >
                        {t("Delete Project")}
                      </Button>
                    )}
                </Stack>
              </Grid>
            )}
          <Tabs
            value={tabIndex}
            onChange={handleTabChange}
            variant="scrollable"
          >
            <Tab
              label={t("Project and Client Details")}
              sx={{
                marginInlineEnd:
                  !hasErrorsInTab(1, errors) &&
                  (hasErrorsInTab(2, errors) || hasErrorsInTab(3, errors))
                    ? 1
                    : undefined,
              }}
              icon={
                hasErrorsInTab(0, errors) ? (
                  <Error sx={{ marginInlineEnd: 1 }} color="error" />
                ) : undefined
              }
              iconPosition="end"
            />
            <Tab
              label={t("Project Task Setup")}
              sx={{
                marginInlineEnd:
                  hasErrorsInTab(2, errors) || hasErrorsInTab(3, errors)
                    ? 1
                    : undefined,
              }}
              iconPosition="end"
            />
            <Tab
              label={t("Staff Allocation and Resource")}
              sx={{
                marginInlineEnd:
                  !hasErrorsInTab(2, errors) && hasErrorsInTab(3, errors)
                    ? 1
                    : undefined,
              }}
              icon={
                hasErrorsInTab(2, errors) ? (
                  <Error sx={{ marginInlineEnd: 1 }} color="error" />
                ) : undefined
              }
              iconPosition="end"
            />
            <Tab
              label={t("Milestone")}
              icon={
                hasErrorsInTab(3, errors) ? (
                  <Error sx={{ marginInlineEnd: 1 }} color="error" />
                ) : undefined
              }
              iconPosition="end"
            />
          </Tabs>
          {
            <ProjectClientDetails
              isSubProject={isSubProject}
              mainProjects={mainProjects}
              buildingTypes={buildingTypes}
              workNatures={workNatures}
              contractTypes={contractTypes}
              fundingTypes={fundingTypes}
              locationTypes={locationTypes}
              serviceTypes={serviceTypes}
              allCustomers={allCustomers}
              allSubsidiaries={allSubsidiaries}
              projectCategories={projectCategories}
              customerTypes={customerTypes}
              teamLeads={teamLeads}
              allStaffs={allStaffs}
              isActive={tabIndex === 0}
              isEditMode={isEditMode}
            />
          }
          {
            <TaskSetup
              allTasks={allTasks}
              taskTemplates={taskTemplates}
              isActive={tabIndex === 1}
            />
          }
          {
            <StaffAllocation
              isActive={tabIndex === 2}
              allTasks={allTasks}
              grades={grades}
              allStaffs={allStaffs}
              teamLeads={teamLeads}
            />
          }
          {<Milestone allTasks={allTasks} isActive={tabIndex === 3} />}
          {serverError && (
            <Typography variant="body2" color="error" alignSelf="flex-end">
              {serverError}
            </Typography>
          )}
          <Stack direction="row" justifyContent="flex-end" gap={1}>
            {!isEditMode && (
              <>
                <Button
                  variant="outlined"
                  color="secondary"
                  startIcon={<EditNote />}
                  onClick={saveDraft}
                >
                  {t("Save Draft")}
                </Button>
                {draftId &&
                  <Button
                    variant="outlined"
                    color="error"
                    startIcon={<Delete />}
                    onClick={handleDeleteDraft}
                  >
                    {t("Delete Draft")}
                  </Button>
                }
                <Box sx={{ flex: 1, pointerEvents: "none" }} />
              </>
            )}
            <Button
              variant="outlined"
              startIcon={<Close />}
              onClick={handleCancel}
            >
              {t("Cancel")}
            </Button>
            <Button
              name="submit"
              variant="contained"
              startIcon={<Check />}
              type="submit"
              disabled={submitDisabled}
            >
              {isEditMode ? t("Save") : t("Confirm")}
            </Button>
          </Stack>
        </Stack>
      </FormProvider>
    </>
  );
};

export default CreateProject;
