"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 { Customer, CustomerTable } from "@/app/api/subsidiary";
import { SubsidiaryFormInputs } from "@/app/api/subsidiary/actions";

interface Props {
  customers: Customer[];
}

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

  const initialCustomers = customers.map(customer => ({...customer, customerType: customer.customerType.name}))
  const [filteredCustomer, setFilteredCustomer] = React.useState(initialCustomers);
  const [selectedCustomer, setSelectedCustomer] = React.useState<
    typeof filteredCustomer
  >(initialCustomers.filter((customer) =>
      getValues("addCustomerIds")?.includes(customer.id),
    )
  );

  // Adding / Removing customer
  const addCustomer = React.useCallback((customer: CustomerTable) => {
    setSelectedCustomer((customers) => [...customers, customer]);
  }, []);

  const removeCustomer = React.useCallback((customer: CustomerTable) => {
    setSelectedCustomer((customers) => customers.filter((customers) => customers.id !== customer.id));
  }, []);

  const clearCustomer = React.useCallback(() => {
    if (defaultValues !== undefined) {
      // reset({ addSubsidiaryIds: defaultValues.addSubsidiaryIds })
      resetField("addCustomerIds")
      setSelectedCustomer(initialCustomers.filter((customer) =>
        defaultValues.addCustomerIds?.includes(customer.id),
      ))
    }
  }, [defaultValues]);

  // Sync with form
  useEffect(() => {
    setValue(
      "addCustomerIds",
      selectedCustomer.map((customer) => customer.id),
    );
  }, [selectedCustomer, setValue]);

  const customerPoolColumns = React.useMemo<Column<CustomerTable>[]>(
    () => [
      {
        label: t("Add"),
        name: "id",
        onClick: addCustomer,
        buttonIcon: <PersonAdd />,
      },
      { label: t("Customer Code"), name: "code" },
      { label: t("Customer Name"), name: "name" },
      { label: t("Customer Br No."), name: "brNo" },
      { label: t("Customer Address"), name: "address" },
      { label: t("Customer District"), name: "district" },
      { label: t("Customer Type"), name: "customerType" },
    ],
    [addCustomer, t],
  );

  const allocatedCustomerColumns = React.useMemo<Column<CustomerTable>[]>(
    () => [
      {
        label: t("Remove"),
        name: "id",
        onClick: removeCustomer,
        buttonIcon: <PersonRemove />,
      },
      { label: t("Customer Code"), name: "code" },
      { label: t("Customer Name"), name: "name" },
      { label: t("Customer Br No."), name: "brNo" },
      { label: t("Customer Address"), name: "address" },
      { label: t("Customer District"), name: "district" },
      { label: t("Customer Type"), name: "customerType" },
    ],
    [removeCustomer, 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(() => {
    setFilteredCustomer(
      initialCustomers.filter((customer) => {
        const q = query.toLowerCase();
        return (
          (customer.name.toLowerCase().includes(q) ||
            customer.code.toString().includes(q) ||
            (customer.brNo != null && customer.brNo.toLowerCase().includes(q)))
        );
      }),
    );
  }, [customers, query]);

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

  const resetCustomer = React.useCallback(() => {
    clearQueryInput();
    clearCustomer();
  }, [clearQueryInput, clearCustomer]);

  return (
    <>
      <Card sx={{ display: "block" }}>
        <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
          <Stack gap={2}>
            <Typography variant="overline" display="block">
              {t("Customer 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 customer 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("Customer Pool")} />
              <Tab
                label={`${t("Allocated Customer")} (${selectedCustomer.length})`}
              />
            </Tabs>
            <Box sx={{ marginInline: -3 }}>
              {tabIndex === 0 && (
                <SearchResults
                  noWrapper
                  items={differenceBy(filteredCustomer, selectedCustomer, "id")}
                  columns={customerPoolColumns}
                />
              )}
              {tabIndex === 1 && (
                <SearchResults
                  noWrapper
                  items={selectedCustomer}
                  columns={allocatedCustomerColumns}
                />
              )}
            </Box>
          </Stack>
          <CardActions sx={{ justifyContent: "flex-end" }}>
            <Button variant="text" startIcon={<RestartAlt />} onClick={resetCustomer}>
              {t("Reset")}
            </Button>
          </CardActions>
        </CardContent>
      </Card>
    </>
  );
};

export default CustomerAllocation;