"use client";

import { useTranslation } from "react-i18next";
import React, { useEffect } from "react";
import RestartAlt from "@mui/icons-material/RestartAlt";
import SearchResults, { Column } from "../SearchResults";
import { Search, Clear, PersonAdd, PersonRemove } from "@mui/icons-material";
import {
  Stack,
  Typography,
  Grid,
  TextField,
  InputAdornment,
  IconButton,
  Box,
  Button,
  Card,
  CardActions,
  CardContent,
  TabsProps,
  Tab,
  Tabs,
} from "@mui/material";
import differenceBy from "lodash/differenceBy";
import { useFormContext } from "react-hook-form";
import { CustomerFormInputs } from "@/app/api/customer/actions";
import { Subsidiary, SubsidiaryTable } from "@/app/api/customer";

interface Props {
  subsidiaries: Subsidiary[];
}

const SubsidiaryAllocation: React.FC<Props> = ({
  subsidiaries,
}) => {
  const { t } = useTranslation();
  const { setValue, getValues, formState: { defaultValues }, reset, resetField } = useFormContext<CustomerFormInputs>();

  const initialSubsidiaries = subsidiaries.map(subsidiary => ({...subsidiary, subsidiaryType: subsidiary.subsidiaryType.name}))
  const [filteredSubsidiary, setFilteredSubsidiary] = React.useState(initialSubsidiaries);
  const [selectedSubsidiary, setSelectedSubsidiary] = React.useState<
    typeof filteredSubsidiary
  >(initialSubsidiaries.filter((subsidiary) =>
      getValues("addSubsidiaryIds")?.includes(subsidiary.id),
    )
  );

  // Adding / Removing staff
  const addSubsidiary = React.useCallback((subsidiary: SubsidiaryTable) => {
    setSelectedSubsidiary((subsidiaries) => [...subsidiaries, subsidiary]);
  }, []);

  const removeSubsidiary = React.useCallback((subsidiary: SubsidiaryTable) => {
    setSelectedSubsidiary((subsidiaries) => subsidiaries.filter((s) => s.id !== subsidiary.id));
  }, []);

  const clearSubsidiary = React.useCallback(() => {
    if (defaultValues !== undefined) {
      // reset({ addSubsidiaryIds: defaultValues.addSubsidiaryIds })
      resetField("addSubsidiaryIds")
      setSelectedSubsidiary(initialSubsidiaries.filter((subsidiary) =>
        defaultValues.addSubsidiaryIds?.includes(subsidiary.id),
      ))
    }
  }, [defaultValues]);

  // Sync with form
  useEffect(() => {
    setValue(
      "addSubsidiaryIds",
      selectedSubsidiary.map((subsidiary) => subsidiary.id),
    );
  }, [selectedSubsidiary, setValue]);

  const subsidiaryPoolColumns = React.useMemo<Column<SubsidiaryTable>[]>(
    () => [
      {
        label: t("Add"),
        name: "id",
        onClick: addSubsidiary,
        buttonIcon: <PersonAdd />,
      },
      { label: t("Subsidiary Code"), name: "code" },
      { label: t("Subsidiary Name"), name: "name" },
      { label: t("Subsidiary Br No."), name: "brNo" },
      // { label: t("Subsidiary Contact Name"), name: "contactName" },
      // { label: t("Subsidiary Phone"), name: "phone" },
      { label: t("Subsidiary Address"), name: "address" },
      { label: t("Subsidiary District"), name: "district" },
      // { label: t("Subsidiary Email"), name: "email" },
      { label: t("Subsidiary Type"), name: "subsidiaryType" },
    ],
    [addSubsidiary, t],
  );

  const allocatedSubsidiaryColumns = React.useMemo<Column<SubsidiaryTable>[]>(
    () => [
      {
        label: t("Remove"),
        name: "id",
        onClick: removeSubsidiary,
        buttonIcon: <PersonRemove />,
      },
      { label: t("Subsidiary Code"), name: "code" },
      { label: t("Subsidiary Name"), name: "name" },
      { label: t("Subsidiary Br No."), name: "brNo" },
      // { label: t("Subsidiary Contact Name"), name: "contactName" },
      // { label: t("Subsidiary Phone"), name: "phone" },
      { label: t("Subsidiary Address"), name: "address" },
      { label: t("Subsidiary District"), name: "district" },
      // { label: t("Subsidiary Email"), name: "email" },
      { label: t("Subsidiary Type"), name: "subsidiaryType" },
    ],
    [removeSubsidiary, t],
  );

  // Query related
  const [query, setQuery] = React.useState("");
  const onQueryInputChange = React.useCallback<
    React.ChangeEventHandler<HTMLInputElement>
  >((e) => {
    setQuery(e.target.value);
  }, []);
  const clearQueryInput = React.useCallback(() => {
    setQuery("");
  }, []);

  React.useEffect(() => {
    setFilteredSubsidiary(
      initialSubsidiaries.filter((subsidiary) => {
        const q = query.toLowerCase();
        return (
          (subsidiary.name.toLowerCase().includes(q) ||
            subsidiary.code.toString().includes(q) ||
            (subsidiary.brNo != null && subsidiary.brNo.toLowerCase().includes(q)))
        );
      }),
    );
  }, [subsidiaries, query]);

  // Tab related
  const [tabIndex, setTabIndex] = React.useState(0);
  const handleTabChange = React.useCallback<NonNullable<TabsProps["onChange"]>>(
    (_e, newValue) => {
      setTabIndex(newValue);
    },
    [],
  );

  const resetSubsidiary = React.useCallback(() => {
    clearQueryInput();
    clearSubsidiary();
  }, [clearQueryInput, clearSubsidiary]);

  return (
    <>
      <Card sx={{ display: "block" }}>
        <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
          <Stack gap={2}>
            <Typography variant="overline" display="block">
              {t("Subsidiary Allocation")}
            </Typography>
            <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
              <Grid item xs={6} display="flex" alignItems="center">
                <Search sx={{ marginInlineEnd: 1 }} />
                <TextField
                  variant="standard"
                  fullWidth
                  onChange={onQueryInputChange}
                  value={query}
                  placeholder={t("Search by subsidiary code, name or br no.")}
                  InputProps={{
                    endAdornment: query && (
                      <InputAdornment position="end">
                        <IconButton onClick={clearQueryInput}>
                          <Clear />
                        </IconButton>
                      </InputAdornment>
                    ),
                  }}
                />
              </Grid>
            </Grid>
            <Tabs value={tabIndex} onChange={handleTabChange}>
              <Tab label={t("Subsidiary Pool")} />
              <Tab
                label={`${t("Allocated Subsidiary")} (${selectedSubsidiary.length})`}
              />
            </Tabs>
            <Box sx={{ marginInline: -3 }}>
              {tabIndex === 0 && (
                <SearchResults
                  noWrapper
                  items={differenceBy(filteredSubsidiary, selectedSubsidiary, "id")}
                  columns={subsidiaryPoolColumns}
                />
              )}
              {tabIndex === 1 && (
                <SearchResults
                  noWrapper
                  items={selectedSubsidiary}
                  columns={allocatedSubsidiaryColumns}
                />
              )}
            </Box>
          </Stack>
          <CardActions sx={{ justifyContent: "flex-end" }}>
            <Button variant="text" startIcon={<RestartAlt />} onClick={resetSubsidiary}>
              {t("Reset")}
            </Button>
          </CardActions>
        </CardContent>
      </Card>
    </>
  );
};

export default SubsidiaryAllocation;