"use client";

import Stack from "@mui/material/Stack";
import Box from "@mui/material/Box";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Grid from "@mui/material/Grid";
import TextField from "@mui/material/TextField";
import { NumericFormat } from 'react-number-format';
import Typography from "@mui/material/Typography";
import { useTranslation } from "react-i18next";
import Button from "@mui/material/Button";
import { Controller, useFormContext } from "react-hook-form";
import { CreateProjectInputs } from "@/app/api/projects/actions";
import {
  BuildingType,
  ContractType,
  FundingType,
  LocationType,
  MainProject,
  ProjectCategory,
  ServiceType,
  WorkNature,
} from "@/app/api/projects";
import { StaffResult } from "@/app/api/staff";
import {
  Contact,
  Customer,
  CustomerType,
  Subsidiary,
} from "@/app/api/customer";
import Link from "next/link";
import React, { useEffect, useMemo, useState } from "react";
import { fetchCustomer } from "@/app/api/customer/actions";
import uniq from "lodash/uniq";
import ControlledAutoComplete from "../ControlledAutoComplete/ControlledAutoComplete";
import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import dayjs, { Dayjs } from 'dayjs';
import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil";

interface Props {
  isActive: boolean;
  isSubProject: boolean;
  isEditMode: boolean;
  mainProjects?: MainProject[];
  projectCategories: ProjectCategory[];
  teamLeads: StaffResult[];
  allStaffs: StaffResult[];
  allCustomers: Customer[];
  allSubsidiaries: Subsidiary[];
  serviceTypes: ServiceType[];
  contractTypes: ContractType[];
  fundingTypes: FundingType[];
  locationTypes: LocationType[];
  buildingTypes: BuildingType[];
  workNatures: WorkNature[];
  customerTypes: CustomerType[];
}

const ProjectClientDetails: React.FC<Props> = ({
  isActive,
  isSubProject,
  isEditMode,
  mainProjects,
  projectCategories,
  teamLeads,
  allStaffs,
  allCustomers,
  allSubsidiaries,
  serviceTypes,
  contractTypes,
  fundingTypes,
  locationTypes,
  buildingTypes,
  customerTypes,
  workNatures,
}) => {
  const {     
    t,
    i18n: { language }, 
  } = useTranslation();
  const {
    register,
    formState: { errors, defaultValues, touchedFields },
    watch,
    control,
    setValue,
    getValues,
    reset,
    resetField,
    setError,
    clearErrors
  } = useFormContext<CreateProjectInputs>();

  const subsidiaryMap = useMemo<{
    [id: Subsidiary["id"]]: Subsidiary;
  }>(
    () => allSubsidiaries.reduce((acc, sub) => ({ ...acc, [sub.id]: sub }), {}),
    [allSubsidiaries],
  );

  const selectedCustomerId = watch("clientId");
  const [customerContacts, setCustomerContacts] = useState<Contact[]>([]);
  const [subsidiaryContacts, setSubsidiaryContacts] = useState<Contact[]>([]);
  const [customerSubsidiaryIds, setCustomerSubsidiaryIds] = useState<number[]>(
    [],
  );

  const selectedCustomerContactId = watch("clientContactId");
  const selectedCustomerContact = useMemo(
    () =>
      subsidiaryContacts.length > 0
        ? subsidiaryContacts.find(
            (contact) => contact.id === selectedCustomerContactId,
          )
        : customerContacts.find(
            (contact) => contact.id === selectedCustomerContactId,
          ),
    [subsidiaryContacts, customerContacts, selectedCustomerContactId],
  );

  // get customer (client) contact combo
  const clientSubsidiaryId = watch("clientSubsidiaryId");
  useEffect(() => {
    if (selectedCustomerId !== undefined) {
      fetchCustomer(selectedCustomerId).then(
        ({ contacts, subsidiaryIds, customer }) => {
          // console.log(contacts)
          // console.log(subsidiaryIds)
          setCustomerContacts(contacts);
          setCustomerSubsidiaryIds(subsidiaryIds);
          setValue(
            "clientTypeId",
            touchedFields["clientTypeId"]
              ? customer.customerType.id
              : defaultValues?.clientTypeId || customer.customerType.id,
            {
              shouldTouch: isEditMode,
            },
          );
          if (subsidiaryIds.length > 0)
            setValue(
              "clientSubsidiaryId",
              clientSubsidiaryId !== undefined && clientSubsidiaryId !== null
                ? subsidiaryIds.includes(clientSubsidiaryId)
                  ? clientSubsidiaryId
                  : null
                : null,
            );
          // if (contacts.length > 0) setValue("clientContactId", contacts[0].id)
          // else setValue("clientContactId", undefined)
        },
      );
    }
  }, [selectedCustomerId]);

  useEffect(() => {
    if (Boolean(clientSubsidiaryId)) {
      // get subsidiary contact combo
      const contacts = allSubsidiaries.find(
        (subsidiary) => subsidiary.id === clientSubsidiaryId,
      )!.subsidiaryContacts;
      setSubsidiaryContacts(() => contacts);
      setValue(
        "clientContactId",
        selectedCustomerId === defaultValues?.clientId &&
          Boolean(defaultValues?.clientSubsidiaryId)
          ? contacts.find(
              (contact) => contact?.id === defaultValues?.clientContactId,
            )?.id ?? contacts[0]?.id
          : contacts[0]?.id,
      );
      setValue("isSubsidiaryContact", true);
    } else if (customerContacts?.length > 0) {
      setSubsidiaryContacts(() => []);
      setValue(
        "clientContactId",
        selectedCustomerId === defaultValues?.clientId &&
          !Boolean(defaultValues?.clientSubsidiaryId)
          ? customerContacts.find(
              (contact) => contact.id === defaultValues.clientContactId,
            )?.id ?? customerContacts[0].id
          : customerContacts[0].id,
      );
      setValue("isSubsidiaryContact", false);
    }
  }, [customerContacts, clientSubsidiaryId, selectedCustomerId]);

  // Automatically add the team lead to the allocated staff list
  const selectedTeamLeadId = watch("projectLeadId");
  useEffect(() => {
    if (selectedTeamLeadId !== undefined) {
      const currentStaffIds = getValues("allocatedStaffIds");
      const newList = uniq([...currentStaffIds, selectedTeamLeadId]);
      setValue("allocatedStaffIds", newList);
    }
  }, [getValues, selectedTeamLeadId, setValue]);

  // List of possible sub team lead (staffs by team)
  const subTeamLeads = useMemo<StaffResult[]>(() => {
    if (!selectedTeamLeadId) return [];
    const teamLead = teamLeads.find(tl => tl.id === selectedTeamLeadId);
    return teamLead ? allStaffs.filter(staff => staff.team === teamLead.team) : [];
  }, [selectedTeamLeadId, teamLeads, allStaffs]);

  // Automatically update the project & client details whene select a main project
  const mainProjectId = watch("mainProjectId");
  useEffect(() => {
    if (
      mainProjectId !== undefined &&
      mainProjects !== undefined &&
      !isEditMode
    ) {
      const mainProject = mainProjects.find(
        (project) => project.projectId === mainProjectId,
      );

      if (mainProject !== undefined) {

        const teamLeadIds = teamLeads.map((teamLead) => teamLead.id)
        const subTeamLeadIds = subTeamLeads.map((_subTeamLead) => _subTeamLead.id)
        setValue("projectName", mainProject.projectName);
        setValue("projectCategoryId", mainProject.projectCategoryId);

        // set project lead id to the first team lead id if the main project lead id is not in the team lead list
        setValue("projectLeadId", teamLeadIds.find((id) => id === mainProject.projectLeadId) ? mainProject.projectLeadId : teamLeadIds[0] ?? mainProject.projectLeadId);
        setValue("projectSubLeadId", subTeamLeadIds.find((id) => id === mainProject.projectSubLeadId) ? mainProject.projectSubLeadId : subTeamLeadIds[0] ?? mainProject.projectSubLeadId);
        
        setValue("serviceTypeId", mainProject.serviceTypeId);
        setValue("fundingTypeId", mainProject.fundingTypeId);
        setValue("contractTypeId", mainProject.contractTypeId);
        setValue("locationId", mainProject.locationId);
        setValue("buildingTypeIds", mainProject.buildingTypeIds);
        setValue("workNatureIds", mainProject.workNatureIds);
        setValue("projectDescription", mainProject.projectDescription);
        setValue("expectedProjectFee", mainProject.expectedProjectFee);
        setValue("subContractFee", mainProject.subContractFee);
        setValue("isClpProject", mainProject.isClpProject);
        setValue("clientId", mainProject.clientId);
        setValue("clientSubsidiaryId", mainProject.clientSubsidiaryId);
        setValue("clientContactId", mainProject.clientContactId);
      }
    }
  }, [getValues, mainProjectId, setValue, isEditMode]);

  // const buildingTypeIdNameMap = buildingTypes.reduce<{ [id: number]: string }>(
  //   (acc, building) => ({ ...acc, [building.id]: building.name }),
  //   {},
  // );

  // const workNatureIdNameMap = workNatures.reduce<{ [id: number]: string }>(
  //   (acc, wn) => ({ ...acc, [wn.id]: wn.name }),
  //   {},
  // );
  const planStart = watch("projectPlanStart")
  const planEnd = watch("projectPlanEnd")

  useEffect(() => {
    let hasErrors = false
    if(
      !planStart || new Date(planStart) > new Date(planEnd)
    ){
      hasErrors = true;
    }
    if(
      !planEnd || new Date(planStart) > new Date(planEnd)
    ){
      hasErrors = true;
    }
    if(hasErrors){
      setError("projectPlanStart", {
        message: "Project Plan Start date is not valid",
        type: "required",
      });
      setError("projectPlanEnd", {
        message: "Project Plan End date is not valid",
        type: "required",
      });
    }else{
      clearErrors("projectPlanStart")
      clearErrors("projectPlanEnd")
    }
  },[planStart, planEnd])
  
  return (
    <Card sx={{ display: isActive ? "block" : "none" }}>
      <CardContent component={Stack} spacing={4}>
        <Box>
          <Typography variant="overline" display="block" marginBlockEnd={1}>
            {t("Project Details")}
          </Typography>
          <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
            {isSubProject && mainProjects !== undefined && (
              <>
                <Grid item xs={6}>
                  <ControlledAutoComplete
                    control={control}
                    options={[
                      ...mainProjects.map((mainProject) => ({
                        id: mainProject.projectId,
                        label: `${mainProject.projectCode} - ${mainProject.projectName}`,
                      })),
                    ]}
                    name="mainProjectId"
                    label={t("Main Project")}
                    noOptionsText={t("No Main Project")}
                    disabled={isEditMode}
                  />
                </Grid>
                <Grid item sx={{ display: { xs: "none", sm: "block" } }} />
              </>
            )}
            <Grid item xs={6}>
              <TextField
                label={t("Project Code")}
                fullWidth
                // disabled={isSubProject && mainProjects !== undefined}
                {...register("projectCode", {
                  required:
                    !(isSubProject && mainProjects !== undefined) &&
                    "Project code required!",
                })}
                error={Boolean(errors.projectCode)}
              />
            </Grid>
            <Grid item xs={6}>
              <TextField
                label={t("Project Name")}
                fullWidth
                {...register("projectName", {
                  required: "Project name required!",
                })}
                error={Boolean(errors.projectName)}
              />
            </Grid>
            <Grid item xs={3}>
              <LocalizationProvider
                  dateAdapter={AdapterDayjs}
                  adapterLocale={`${language}-hk`}
                  >
                  <DatePicker
                    sx={{ width: "100%" }}
                    label={t("Plan Start")}
                    format="YYYY/MM/DD"
                    value={planStart ? dayjs(planStart) : null}
                    onChange={(date) => {
                        if (!date) return;
                        setValue("projectPlanStart", date.format(INPUT_DATE_FORMAT));
                      }}
                      slotProps={{
                          textField: {
                              // required: true,
                              error:
                              // Boolean(errors.projectPlanStart)
                              // || 
                              new Date(planStart) > new Date(planEnd)
                              || Boolean(errors.projectPlanStart)
                              ,
                          },
                      }}
                      />
                </LocalizationProvider>
            </Grid>
            <Grid item xs={3}>
            <LocalizationProvider
                  dateAdapter={AdapterDayjs}
                  adapterLocale={`${language}-hk`}
                  >
                  <DatePicker
                    sx={{ width: "100%" }}
                    label={t("Plan End")}
                    format="YYYY/MM/DD"
                    value={planEnd ? dayjs(planEnd) : null}
                    onChange={(date) => {
                        if (!date) return;
                        setValue("projectPlanEnd", date.format(INPUT_DATE_FORMAT));
                      }}
                      slotProps={{
                          textField: {
                              // required: true,
                              error:
                              // Boolean(errors.projectPlanEnd)
                              // || 
                              new Date(planStart) > new Date(planEnd)
                              || Boolean(errors.projectPlanEnd)
                              ,
                          },
                      }}
                      />
                </LocalizationProvider>
            </Grid>
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={projectCategories}
                name="projectCategoryId"
                label={t("Project Category")}
                noOptionsText={t("No Project Category")}
              />
            </Grid>
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={teamLeads.map((staff) => ({
                  ...staff,
                  label: `${staff.staffId} - ${staff.name} (${staff.team})`,
                }))}
                name="projectLeadId"
                label={t("Team Lead")}
                noOptionsText={t("No Team Lead")}
              />
            </Grid>
            {subTeamLeads.length > 0 && <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={
                  [{id: undefined, label: 'N/A'},
                  ...subTeamLeads
                  // .filter(staff => staff.team === teamLeads.find(teamLead => teamLead.id === selectedTeamLeadId)?.team)
                  .map((staff) => ({
                  ...staff,
                  label: `${staff.staffId} - ${staff.name} (${staff.team})`,
                }))]}
                name="projectSubLeadId"
                label={t("Sub Team Lead")}
                noOptionsText={t("No Sub Team Lead")}
              />
            </Grid>}
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={serviceTypes}
                name="serviceTypeId"
                label={t("Service Type")}
                noOptionsText={t("No Service Type")}
              />
            </Grid>
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={fundingTypes}
                name="fundingTypeId"
                label={t("Funding Type")}
                noOptionsText={t("No Funding Type")}
              />
            </Grid>
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={contractTypes}
                name="contractTypeId"
                label={t("Contract Type")}
                noOptionsText={t("No Contract Type")}
              />
            </Grid>
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={locationTypes}
                name="locationId"
                label={t("Location")}
                noOptionsText={t("No Location")}
              />
            </Grid>
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={buildingTypes}
                name="buildingTypeIds"
                label={t("Building Types")}
                noOptionsText={t("No Building Types")}
                isMultiple
              />
            </Grid>

            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={workNatures}
                name="workNatureIds"
                label={t("Work Nature")}
                noOptionsText={t("No Work Nature")}
                isMultiple
              />
            </Grid>

            <Grid item xs={6}>
              <TextField
                label={t("Project Description")}
                fullWidth
                {...register("projectDescription", {
                  required: "Please enter a description",
                })}
                error={Boolean(errors.projectDescription)}
              />
            </Grid>
            <Grid item xs={6}>
              <Controller
                control={control}
                name="expectedProjectFee"
                render={({ field: { onChange, onBlur, name, value, ref } }) => (
                  <NumericFormat
                    label={t("Expected Total Project Fee")}
                    fullWidth
                    prefix="HK$"
                    onValueChange={(values) => {
                      // console.log(values)
                      onChange(values.floatValue)
                    }}
                    customInput={TextField}
                    thousandSeparator
                    valueIsNumericString
                    decimalScale={2}
                    fixedDecimalScale
                    name={name}
                    value={value}
                    onBlur={onBlur}
                    inputRef={ref}
                  />
                )}
              />
              {/* <TextField
                label={t("Expected Total Project Fee")}
                fullWidth
                type="number"
                inputProps={{ 
                  step: "0.01",
                }}
                {...register("expectedProjectFee", { valueAsNumber: true })}
              /> */}
            </Grid>

            <Grid item xs={6}>
              <Controller
                control={control}
                name="subContractFee"
                render={({ field: { onChange, onBlur, name, value, ref } }) => (
                  <NumericFormat
                    label={t("Sub-Contract Fee")}
                    fullWidth
                    prefix="HK$"
                    onValueChange={(values) => {
                      // console.log(values)
                      onChange(values.floatValue)
                    }}
                    customInput={TextField}
                    thousandSeparator
                    valueIsNumericString
                    decimalScale={2}
                    fixedDecimalScale
                    name={name}
                    value={value}
                    onBlur={onBlur}
                    inputRef={ref}
                  />
                )}
              />
              {/* <TextField
                label={t("Sub-Contract Fee")}
                fullWidth
                type="number"
                inputProps={{ step: "0.01" }}
                // InputLabelProps={{
                //   shrink: Boolean(watch("subContractFee")),
                // }}
                {...register("subContractFee", { valueAsNumber: true })}
              /> */}
            </Grid>

            {/* <Grid item xs={6}>
              <Checkbox
                {...register("isClpProject")}
                checked={Boolean(watch("isClpProject"))}
                disabled={isSubProject && mainProjects !== undefined}
              />
              <Typography variant="overline" display="inline">
                {t("CLP Project")}
              </Typography>
            </Grid> */}
          </Grid>
        </Box>

        <Box>
          <Stack
            direction="row"
            alignItems="center"
            marginBlockEnd={1}
            spacing={2}
          >
            <Typography variant="overline" display="block">
              {t("Client Details")}
            </Typography>
            {/* <Button LinkComponent={Link} href="/settings/customer">
              {t("Add or Edit Clients")}
            </Button> */}
          </Stack>
          <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={allCustomers.map((customer) => ({
                  ...customer,
                  label: `${customer.name}`,
                  // label: `${customer.code} - ${customer.name}`,
                }))}
                name="clientId"
                label={t("Client")}
                noOptionsText={t("No Client")}
                rules={{
                  required: "Please select a client",
                }}
              />
            </Grid>
            {/* <Grid item sx={{ display: { xs: "none", sm: "block" } }} /> */}
            <Grid item xs={6}>
              <ControlledAutoComplete
                control={control}
                options={customerTypes}
                name="clientTypeId"
                label={t("Client Type")}
                noOptionsText={t("No Client Type")}
                rules={{
                  required: "Please select a client type",
                }}
              />
            </Grid>
            </Grid>
            <Grid item sx={{ display: { xs: "none", sm: "block" } }} />
            {customerContacts.length > 0 && (
              <Box>
              <Stack
                direction="row"
                alignItems="center"
                marginBlockEnd={1}
                spacing={2}
              >
                <Typography variant="overline" display="block">
                  {t("Subsidiary Details")}
                </Typography>
              </Stack>
              <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
                <Grid item xs={6}>
                  <ControlledAutoComplete
                    control={control}
                    options={[
                      { label: t("No Subsidiary") },
                      ...customerSubsidiaryIds
                        .filter((subId) => subsidiaryMap[subId])
                        .map((subsidiaryId, index) => {
                          const subsidiary = subsidiaryMap[subsidiaryId];
                          return {
                            id: subsidiary.id,
                            label: `${subsidiary.name}`,
                            // label: `${subsidiary.code} - ${subsidiary.name}`,
                          };
                        }),
                    ]}
                    name="clientSubsidiaryId"
                    label={t("Client Subsidiary")}
                    noOptionsText={t("No Client Subsidiary")}
                  />
                </Grid>
                <Grid item xs={6}>
                  <ControlledAutoComplete
                    control={control}
                    options={
                      Boolean(watch("clientSubsidiaryId"))
                        ? subsidiaryContacts
                        : customerContacts
                    }
                    name="clientContactId"
                    label={t("Client Lead")}
                    noOptionsText={t("No Client Lead")}
                    rules={{
                      validate: (value) => {
                        if (
                          customerContacts.length > 0 &&
                          !customerContacts.find(
                            (contact) => contact.id === value,
                          ) &&
                          subsidiaryContacts?.length > 0 &&
                          !subsidiaryContacts.find(
                            (contact) => contact.id === value,
                          )
                        ) {
                          return t("Please provide a valid contact");
                        } else return true;
                      },
                    }}
                  />
                </Grid>
                <Grid container sx={{ display: { xs: "none", sm: "block" } }} />
                <Grid item xs={6}>
                  <TextField
                    label={t("Client Lead Phone Number")}
                    fullWidth
                    InputProps={{
                      readOnly: true,
                    }}
                    value={selectedCustomerContact?.phone || ""}
                  />
                </Grid>
                <Grid item xs={6}>
                  <TextField
                    label={t("Client Lead Email")}
                    fullWidth
                    InputProps={{
                      readOnly: true,
                    }}
                    value={selectedCustomerContact?.email || ""}
                  />
                </Grid>
                </Grid>
              </Box>
            )}
          {/* </Grid> */}
        </Box>
        {/* <CardActions sx={{ justifyContent: "flex-end" }}>
          <Button variant="text" startIcon={<RestartAlt />}>
            {t("Reset")}
          </Button>
        </CardActions> */}
      </CardContent>
    </Card>
  );
};

export default ProjectClientDetails;
