"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 FormControl from "@mui/material/FormControl";
import Grid from "@mui/material/Grid";
import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import Select from "@mui/material/Select";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import { useTranslation } from "react-i18next";
import CardActions from "@mui/material/CardActions";
import RestartAlt from "@mui/icons-material/RestartAlt";
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,
  ProjectCategory,
  ServiceType,
  WorkNature,
} from "@/app/api/projects";
import { StaffResult } from "@/app/api/staff";
import { Contact, Customer, 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 { Checkbox, ListItemText } from "@mui/material";
import uniq from "lodash/uniq";

interface Props {
  isActive: boolean;
  projectCategories: ProjectCategory[];
  teamLeads: StaffResult[];
  allCustomers: Customer[];
  allSubsidiaries: Subsidiary[];
  serviceTypes: ServiceType[];
  contractTypes: ContractType[];
  fundingTypes: FundingType[];
  locationTypes: LocationType[];
  buildingTypes: BuildingType[];
  workNatures: WorkNature[];
}

const ProjectClientDetails: React.FC<Props> = ({
  isActive,
  projectCategories,
  teamLeads,
  allCustomers,
  allSubsidiaries,
  serviceTypes,
  contractTypes,
  fundingTypes,
  locationTypes,
  buildingTypes,
  workNatures,
}) => {
  const { t } = useTranslation();
  const {
    register,
    formState: { errors },
    watch,
    control,
    setValue,
    getValues,
  } = useFormContext<CreateProjectInputs>();

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

  const selectedCustomerId = watch("clientId");
  const selectedCustomer = useMemo(
    () => allCustomers.find((c) => c.id === selectedCustomerId),
    [allCustomers, selectedCustomerId],
  );

  const [customerContacts, setCustomerContacts] = useState<Contact[]>([]);
  const [customerSubsidiaryIds, setCustomerSubsidiaryIds] = useState<number[]>(
    [],
  );

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

  useEffect(() => {
    if (selectedCustomerId !== undefined) {
      fetchCustomer(selectedCustomerId).then(({ contacts, subsidiaryIds }) => {
        setCustomerContacts(contacts);
        setCustomerSubsidiaryIds(subsidiaryIds);
      });
    }
  }, [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]);

  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 }),
    {},
  );

  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 }}>
            <Grid item xs={6}>
              <TextField
                label={t("Project Code")}
                fullWidth
                {...register("projectCode", {
                  required: "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={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Project Category")}</InputLabel>
                <Controller
                  defaultValue={projectCategories[0].id}
                  control={control}
                  name="projectCategoryId"
                  render={({ field }) => (
                    <Select label={t("Project Category")} {...field}>
                      {projectCategories.map((category, index) => (
                        <MenuItem
                          key={`${category.id}-${index}`}
                          value={category.id}
                        >
                          {t(category.name)}
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>
            <Grid item xs={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Team Lead")}</InputLabel>
                <Controller
                  defaultValue={teamLeads[0].id}
                  control={control}
                  name="projectLeadId"
                  render={({ field }) => (
                    <Select label={t("Team Lead")} {...field}>
                      {teamLeads.map((staff, index) => (
                        <MenuItem key={`${staff.id}-${index}`} value={staff.id}>
                          {`${staff.staffId} - ${staff.name} (${staff.team})`}
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>
            <Grid item xs={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Service Type")}</InputLabel>
                <Controller
                  defaultValue={serviceTypes[0].id}
                  control={control}
                  name="serviceTypeId"
                  render={({ field }) => (
                    <Select label={t("Service Type")} {...field}>
                      {serviceTypes.map((type, index) => (
                        <MenuItem key={`${type.id}-${index}`} value={type.id}>
                          {type.name}
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>
            <Grid item xs={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Funding Type")}</InputLabel>
                <Controller
                  defaultValue={fundingTypes[0].id}
                  control={control}
                  name="fundingTypeId"
                  render={({ field }) => (
                    <Select label={t("Funding Type")} {...field}>
                      {fundingTypes.map((type, index) => (
                        <MenuItem key={`${type.id}-${index}`} value={type.id}>
                          {type.name}
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>
            <Grid item xs={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Contract Type")}</InputLabel>
                <Controller
                  defaultValue={contractTypes[0].id}
                  control={control}
                  name="contractTypeId"
                  render={({ field }) => (
                    <Select label={t("Contract Type")} {...field}>
                      {contractTypes.map((type, index) => (
                        <MenuItem key={`${type.id}-${index}`} value={type.id}>
                          {type.name}
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>
            <Grid item xs={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Location")}</InputLabel>
                <Controller
                  defaultValue={locationTypes[0].id}
                  control={control}
                  name="locationId"
                  render={({ field }) => (
                    <Select label={t("Location")} {...field}>
                      {locationTypes.map((type, index) => (
                        <MenuItem key={`${type.id}-${index}`} value={type.id}>
                          {type.name}
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>
            <Grid item xs={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Building Types")}</InputLabel>
                <Controller
                  defaultValue={[]}
                  control={control}
                  name="buildingTypeIds"
                  render={({ field }) => (
                    <Select
                      renderValue={(types) =>
                        types
                          .map((type) => buildingTypeIdNameMap[type])
                          .join(", ")
                      }
                      multiple
                      label={t("Building Types")}
                      {...field}
                    >
                      {buildingTypes.map((type, index) => (
                        <MenuItem key={`${type.id}-${index}`} value={type.id}>
                          <Checkbox
                            checked={field.value.indexOf(type.id) > -1}
                          />
                          <ListItemText primary={type.name} />
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>

            <Grid item xs={6}>
              <FormControl fullWidth>
                <InputLabel>{t("Work Nature")}</InputLabel>
                <Controller
                  defaultValue={[]}
                  control={control}
                  name="workNatureIds"
                  render={({ field }) => (
                    <Select
                      renderValue={(types) =>
                        types
                          .map((type) => workNatureIdNameMap[type])
                          .join(", ")
                      }
                      multiple
                      label={t("Work Nature")}
                      {...field}
                    >
                      {workNatures.map((type, index) => (
                        <MenuItem key={`${type.id}-${index}`} value={type.id}>
                          <Checkbox
                            checked={field.value.indexOf(type.id) > -1}
                          />
                          <ListItemText primary={type.name} />
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </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}>
              <TextField
                label={t("Expected Total Project Fee")}
                fullWidth
                type="number"
                {...register("expectedProjectFee", { valueAsNumber: true })}
              />
            </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}>
              <FormControl fullWidth>
                <InputLabel>{t("Client")}</InputLabel>
                <Controller
                  defaultValue={allCustomers[0].id}
                  control={control}
                  name="clientId"
                  render={({ field }) => (
                    <Select label={t("Client")} {...field}>
                      {allCustomers.map((customer, index) => (
                        <MenuItem
                          key={`${customer.id}-${index}`}
                          value={customer.id}
                        >
                          {`${customer.code} - ${customer.name}`}
                        </MenuItem>
                      ))}
                    </Select>
                  )}
                />
              </FormControl>
            </Grid>
            <Grid item sx={{ display: { xs: "none", sm: "block" } }} />
            <Grid item xs={6}>
              <TextField
                label={t("Client Type")}
                InputProps={{
                  readOnly: true,
                }}
                fullWidth
                value={selectedCustomer?.customerType.name || ""}
              />
            </Grid>
            <Grid item sx={{ display: { xs: "none", sm: "block" } }} />
            {customerContacts.length > 0 && (
              <>
                <Grid item xs={6}>
                  <FormControl
                    fullWidth
                    error={Boolean(errors.clientContactId)}
                  >
                    <InputLabel>{t("Client Lead")}</InputLabel>
                    <Controller
                      rules={{
                        validate: (value) => {
                          if (
                            !customerContacts.find(
                              (contact) => contact.id === value,
                            )
                          ) {
                            return t("Please provide a valid contact");
                          } else return true;
                        },
                      }}
                      defaultValue={customerContacts[0].id}
                      control={control}
                      name="clientContactId"
                      render={({ field }) => (
                        <Select label={t("Client Lead")} {...field}>
                          {customerContacts.map((contact, index) => (
                            <MenuItem
                              key={`${contact.id}-${index}`}
                              value={contact.id}
                            >
                              {contact.name}
                            </MenuItem>
                          ))}
                        </Select>
                      )}
                    />
                  </FormControl>
                </Grid>
                <Grid item 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>
              </>
            )}
            {customerSubsidiaryIds.length > 0 && (
              <Grid item xs={6}>
                <FormControl
                  fullWidth
                  error={Boolean(errors.clientSubsidiaryId)}
                >
                  <InputLabel>{t("Client Subsidiary")}</InputLabel>
                  <Controller
                    rules={{
                      validate: (value) => {
                        if (
                          !customerSubsidiaryIds.find(
                            (subsidiaryId) => subsidiaryId === value,
                          )
                        ) {
                          return t("Please choose a valid subsidiary");
                        } else return true;
                      },
                    }}
                    defaultValue={customerSubsidiaryIds[0]}
                    control={control}
                    name="clientSubsidiaryId"
                    render={({ field }) => (
                      <Select label={t("Client Lead")} {...field}>
                        {customerSubsidiaryIds
                          .filter((subId) => subsidiaryMap[subId])
                          .map((subsidiaryId, index) => {
                            const subsidiary = subsidiaryMap[subsidiaryId];

                            return (
                              <MenuItem
                                key={`${subsidiaryId}-${index}`}
                                value={subsidiaryId}
                              >
                                {`${subsidiary.code} - ${subsidiary.name}`}
                              </MenuItem>
                            );
                          })}
                      </Select>
                    )}
                  />
                </FormControl>
              </Grid>
            )}
          </Grid>
        </Box>
        <CardActions sx={{ justifyContent: "flex-end" }}>
          <Button variant="text" startIcon={<RestartAlt />}>
            {t("Reset")}
          </Button>
        </CardActions>
      </CardContent>
    </Card>
  );
};

export default ProjectClientDetails;
