"use client";

import DoneIcon from "@mui/icons-material/Done";
import Check from "@mui/icons-material/Check";
import Close from "@mui/icons-material/Close";
import Button 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 } from "next/navigation";
import React, { useCallback, 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, 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 { Typography } from "@mui/material";
import { Grade } from "@/app/api/grades";
import { Customer, Subsidiary } from "@/app/api/customer";
import { isEmpty } from "lodash";
import {
  deleteDialog,
  errorDialog,
  submitDialog,
  successDialog,
} from "../Swal/CustomAlerts";
import dayjs from "dayjs";

export interface Props {
  isEditMode: boolean;
  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[];
  grades: Grade[];
}

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

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

  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

        // Tab - Staff Allocation and Resource
        if (data.totalManhour === null || data.totalManhour <= 0) {
          formProps.setError("totalManhour", { message: "totalManhour 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" || new Date(startDate) > new Date(endDate)) {
            formProps.setError("milestones", { message: "milestones is not valid", type: "invalid" })
            setTabIndex(3)
            hasErrors = true
          }

          projectTotal += payments.reduce((acc, payment) => acc + payment.amount, 0)
        })

        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("");

        let title = t("Do you want to submit?");
        let confirmButtonText = t("Submit");
        let successTitle = t("Submit Success");
        let errorTitle = t("Submit Fail");
        const buttonName = (event?.nativeEvent as any).submitter.name;

        if (buttonName === "start") {
          title = t("Do you want to start?");
          confirmButtonText = t("Start");
          successTitle = t("Start Success");
          errorTitle = t("Start Fail");
        } else if (buttonName === "complete") {
          title = t("Do you want to complete?");
          confirmButtonText = t("Complete");
          successTitle = t("Complete Success");
          errorTitle = t("Complete Fail");
        }

        submitDialog(
          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) {
              successDialog(successTitle, t).then(() => {
                router.replace("/projects");
              });
            } else {
              errorDialog(errorTitle, t).then(() => {
                return false;
              });
            }
          },
          t,
          { title: title, confirmButtonText: confirmButtonText },
        );
      } catch (e) {
        setServerError(t("An error has occurred. Please try again later."));
      }
    },
    [router, t],
  );

  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
      ) {
        setTabIndex(0);
      } else if (errors.totalManhour || errors.manhourPercentageByGrade || errors.taskGroups) {
        setTabIndex(2)
      } else if (errors.milestones) {
        setTabIndex(3)
      }
    },
    [],
  );

  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,
      clientId: allCustomers !== undefined ? allCustomers[0].id : undefined,
      ...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 errors = formProps.formState.errors;

  return (
    <>
      <FormProvider {...formProps}>
        <Stack
          spacing={2}
          component="form"
          onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
        >
          {isEditMode && !(formProps.getValues("projectDeleted") === true) && (
            <Stack direction="row" gap={1}>
              {/* {!formProps.getValues("projectActualStart") && ( */}
              {formProps.getValues("projectStatus").toLowerCase() === "pending to start" && (
                <Button
                  name="start"
                  type="submit"
                  variant="contained"
                  startIcon={<PlayArrow />}
                  color="success"
                >
                  {t("Start Project")}
                </Button>
              )}
              {/* {formProps.getValues("projectActualStart") &&
                !formProps.getValues("projectActualEnd") && ( */}
              {formProps.getValues("projectStatus").toLowerCase() === "on-going" && (
                <Button
                  name="complete"
                  type="submit"
                  variant="contained"
                  startIcon={<DoneIcon />}
                  color="info"
                >
                  {t("Complete Project")}
                </Button>
              )}
              {!(
                // formProps.getValues("projectActualStart") &&
                // formProps.getValues("projectActualEnd")
                formProps.getValues("projectStatus") === "Completed" ||
                formProps.getValues("projectStatus") === "Deleted"
              ) && (
                  <Button
                    variant="outlined"
                    startIcon={<Delete />}
                    color="error"
                    onClick={handleDelete}
                  >
                    {t("Delete Project")}
                  </Button>
                )}
            </Stack>
          )}
          <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}
              teamLeads={teamLeads}
              isActive={tabIndex === 0}
              isEditMode={isEditMode}
            />
          }
          {
            <TaskSetup
              allTasks={allTasks}
              taskTemplates={taskTemplates}
              isActive={tabIndex === 1}
            />
          }
          {
            <StaffAllocation
              isActive={tabIndex === 2}
              allTasks={allTasks}
              grades={grades}
              allStaffs={allStaffs}
            />
          }
          {<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}>
            <Button
              variant="outlined"
              startIcon={<Close />}
              onClick={handleCancel}
            >
              {t("Cancel")}
            </Button>
            <Button
              variant="contained"
              startIcon={<Check />}
              type="submit"
              disabled={
                formProps.getValues("projectDeleted") === true || formProps.getValues("projectStatus") === "Deleted" ||
                (!!formProps.getValues("projectActualStart") &&
                  !!formProps.getValues("projectActualEnd"))
              }
            >
              {isEditMode ? t("Save") : t("Confirm")}
            </Button>
          </Stack>
        </Stack>
      </FormProvider>
    </>
  );
};

export default CreateProject;
