"use client";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import {
  Add,
  Clear,
  PersonAdd,
  PersonRemove,
  Remove,
  Search,
} from "@mui/icons-material";
import { useTranslation } from "react-i18next";
import {
  FieldErrors,
  FormProvider,
  SubmitErrorHandler,
  SubmitHandler,
  useForm,
  useFormContext,
} from "react-hook-form";
import {
  Box,
  Card,
  CardContent,
  Grid,
  IconButton,
  InputAdornment,
  Stack,
  Tab,
  Tabs,
  TabsProps,
  TextField,
  Typography,
} from "@mui/material";
import { differenceBy } from "lodash";
import { UserInputs } from "@/app/api/user/actions";
import { auth } from "@/app/api/group/actions";
import SearchResults, { Column } from "../SearchResults";

export interface Props {
  auths: auth[];
}

const AuthAllocation: React.FC<Props> = ({ auths }) => {
  const { t } = useTranslation();
  const searchParams = useSearchParams();
  const id = parseInt(searchParams.get("id") || "0");
  const {
    setValue,
    getValues,
    formState: { defaultValues },
    reset,
    resetField,
  } = useFormContext<UserInputs>();
  const initialAuths = auths.map((u) => ({ ...u })).sort((a, b) => a.id - b.id);
  const [filteredAuths, setFilteredAuths] = useState(initialAuths);
  const [selectedAuths, setSelectedAuths] = useState<typeof filteredAuths>(
    () => {
      return filteredAuths.filter(
        (s) => getValues("addAuthIds")?.includes(s.id)
      );
    }
  );
  const [removeAuthIds, setRemoveAuthIds] = useState<number[]>([]);

  // Adding / Removing Auth
  const addAuth = useCallback((auth: auth) => {
    setSelectedAuths((a) => [...a, auth]);
  }, []);
  const removeAuth = useCallback((auth: auth) => {
    setSelectedAuths((a) => a.filter((a) => a.id !== auth.id));
    setRemoveAuthIds((prevIds) => [...prevIds, auth.id]);
  }, []);

  const clearAuth = useCallback(() => {
    if (defaultValues !== undefined) {
      resetField("addAuthIds");
      setSelectedAuths(
        initialAuths.filter(
          (auth) => defaultValues.addAuthIds?.includes(auth.id)
        )
      );
    }
  }, [defaultValues]);

  // Sync with form
  useEffect(() => {
    setValue(
      "addAuthIds",
      selectedAuths.map((a) => a.id)
    );
    setValue("removeAuthIds", removeAuthIds);
  }, [selectedAuths, removeAuthIds, setValue]);

  const AuthPoolColumns = useMemo<Column<auth>[]>(
    () => [
      {
        label: t("Add"),
        name: "id",
        onClick: addAuth,
        buttonIcon: <Add />,
      },
      { label: t("authority"), name: "authority" },
      { label: t("description"), name: "name" },
    ],
    [addAuth, t]
  );

  const allocatedAuthColumns = useMemo<Column<auth>[]>(
    () => [
      {
        label: t("Remove"),
        name: "id",
        onClick: removeAuth,
        buttonIcon: <Remove color="warning" />,
      },
      { label: t("authority"), name: "authority" },
      { label: t("description"), name: "name" },
    ],
    [removeAuth, selectedAuths, t]
  );

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

  React.useEffect(() => {
    setFilteredAuths(
      initialAuths.filter((a) => 
          (
            a.authority.toLowerCase().includes(query.toLowerCase()) ||
            a.name?.toLowerCase().includes(query.toLowerCase())
          )
      )
    );
  }, [auths, query]);

  const resetAuth = React.useCallback(() => {
    clearQueryInput();
    clearAuth();
  }, [clearQueryInput, clearAuth]);

  const formProps = useForm({});

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

  return (
    <>
      <FormProvider {...formProps}>
        <Card sx={{ display: "block" }}>
          <CardContent
            sx={{ display: "flex", flexDirection: "column", gap: 1 }}
          >
            <Stack gap={2}>
              <Typography variant="overline" display="block">
                {t("Authority")}
              </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 Authority or description or position."
                    )}
                    InputProps={{
                      endAdornment: query && (
                        <InputAdornment position="end">
                          <IconButton onClick={clearQueryInput}>
                            <Clear />
                          </IconButton>
                        </InputAdornment>
                      ),
                    }}
                  />
                </Grid>
              </Grid>
              <Tabs value={tabIndex} onChange={handleTabChange}>
                <Tab label={t("Authority Pool")} />
                <Tab
                  label={`${t("Allocated Authority")} (${
                    selectedAuths.length
                  })`}
                />
              </Tabs>
              <Box sx={{ marginInline: -3 }}>
                {tabIndex === 0 && (
                  <SearchResults
                    noWrapper
                    items={differenceBy(filteredAuths, selectedAuths, "id")}
                    columns={AuthPoolColumns}
                  />
                )}
                {tabIndex === 1 && (
                  <SearchResults
                    noWrapper
                    items={selectedAuths}
                    columns={allocatedAuthColumns}
                  />
                )}
              </Box>
            </Stack>
          </CardContent>
        </Card>
      </FormProvider>
    </>
  );
};
export default AuthAllocation;
