import React, { useEffect, useRef, useState } from 'react';
import { Control, Controller, useForm, UseFormSetValue } from 'react-hook-form';
import {
  Box,
  Grid,
  GridItem,
  IconButton,
  Input,
  MainButton,
  makeToast,
  Menu,
  Text,
} from '@nova-hf/ui';
import { useRouter } from 'next/router';
import {
  AddContractDepartmentInput,
  ContractDepartment,
  useAddContractDepartmentMutation,
  useCustomerNameQuery,
  useDeleteContractDepartmentMutation,
  useDepartmentsQuery,
  useUpdateContractDepartmentMutation,
} from 'typings/graphql';
import { Trans, useTranslation } from 'utils/i18n';

import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal';

type EditableRowProps = {
  control: Control<AddContractDepartmentInput>;
  setValue: UseFormSetValue<AddContractDepartmentInput>;
  defaultValue?: string;
  onSaveClick?: () => void;
  onCancelClick?: () => void;
};
const EditableRow = ({
  control,
  setValue,
  defaultValue,
  onSaveClick,
  onCancelClick,
}: EditableRowProps) => {
  const inputElement = useRef<HTMLInputElement>(null);
  const { t } = useTranslation('stillingar');

  useEffect(() => {
    if (defaultValue) {
      setValue('departmentName', defaultValue);
    }
    if (inputElement.current) {
      inputElement.current.focus();
    }
  }, []);

  return (
    <>
      <GridItem gridColumn={{ sm: 'span6' }}>
        <Controller
          name={'departmentName'}
          control={control}
          render={({ field }) => {
            return (
              <Input
                ref={inputElement}
                name={field.name}
                value={field.value}
                id="departmentNameId"
                label={t('departmentsTab.departmentNameLabel')}
                onChange={(e) => setValue('departmentName', e.target.value ?? '')}
                autoFocus
              />
            );
          }}
        />
      </GridItem>
      <GridItem gridColumn={{ sm: 'span6' }}>
        <Box display="flex" gap={2}>
          <MainButton
            colorScheme="pink"
            text={t('departmentsTab.save')}
            dottedShadow="none"
            onClick={onSaveClick}
          />
          <MainButton
            colorScheme="white"
            text={t('departmentsTab.cancel')}
            dottedShadow="none"
            onClick={onCancelClick}
          />
        </Box>
      </GridItem>
    </>
  );
};

export const Departments = () => {
  const { t } = useTranslation('stillingar');
  const { query } = useRouter();
  const [name, setName] = useState('');
  const [searchTerm, setSearchTerm] = useState<string>();
  const [departmentToDelete, setDepartmentToDelete] = useState<ContractDepartment>();
  const [departmentToEdit, setDepartmentToEdit] = useState<ContractDepartment>();
  const [isAddingNewDepartment, setIsAddingNewDepartment] = useState(false);

  const customerId: string = (query.customerId as string) ?? '';

  const { data: customerNameData } = useCustomerNameQuery({
    variables: { input: { id: customerId } },
    fetchPolicy: 'cache-and-network',
  });

  const { data, loading, error, refetch } = useDepartmentsQuery({
    variables: {
      accountInput: {
        ssn: customerNameData?.customer?.nationalId,
      },
      servicesRequired: false,
    },
    skip: !customerNameData?.customer?.nationalId,
    fetchPolicy: 'cache-and-network',
  });
  const [updateDepartment] = useUpdateContractDepartmentMutation();
  const [deleteDepartment] = useDeleteContractDepartmentMutation();
  const [addDepartment] = useAddContractDepartmentMutation();

  const { control, setValue, reset, watch } = useForm<AddContractDepartmentInput>({
    defaultValues: {
      customerId: '',
      departmentName: '',
    },
  });

  const { departmentName } = watch();

  useEffect(() => {
    if (customerNameData && customerNameData?.customer?.name)
      setName(customerNameData.customer.name);
    else setName(t('departmentsTab.defaultCompanyName'));
  }, [customerNameData]);

  const handleEditDepartment = (selectedDepartment: ContractDepartment) => {
    setDepartmentToEdit(selectedDepartment);
  };

  const handleDeleteDepartment = async () => {
    if (departmentToDelete) {
      try {
        const { data } = await deleteDepartment({
          variables: {
            input: {
              departmentId: departmentToDelete.id,
            },
          },
        });
        if (data?.deleteContractDepartment?.error) {
          const errorMessage: string = data.deleteContractDepartment.error.message;
          makeToast.danger(t('departmentsTab.deleteError'), errorMessage);
        } else {
          setDepartmentToDelete(undefined);
          makeToast.success(t('departmentsTab.deleteSuccess'), '');
          refetch();
        }
      } catch (error) {
        if (error instanceof Error) {
          makeToast.danger(t('departmentsTab.deleteError'), error.message);
        }
      }
    }
  };

  const handleSubmit = async () => {
    if (isAddingNewDepartment) {
      try {
        const { data } = await addDepartment({
          variables: {
            input: {
              customerId: customerId,
              departmentName: departmentName,
            },
          },
        });
        if (data?.addContractDepartment?.department?.id) {
          handleCancelAdd();
          makeToast.success(t('departmentsTab.addSuccess'), '');
          refetch();
        } else {
          makeToast.danger(t('departmentsTab.addError'), '');
        }
      } catch (error) {
        if (error instanceof Error) {
          makeToast.danger(t('departmentsTab.addError'), error.message);
        }
      }
    } else if (departmentToEdit) {
      try {
        const { data } = await updateDepartment({
          variables: {
            input: {
              departmentId: departmentToEdit.id,
              departmentName: departmentName,
            },
          },
        });
        if (data?.updateContractDepartment?.error) {
          const errorMessage: string = data.updateContractDepartment.error.message;
          makeToast.danger(t('departmentsTab.editError'), errorMessage);
        } else {
          handleCancelAdd();
          makeToast.success(t('departmentsTab.editSuccess'), '');

          refetch();
        }
      } catch (error) {
        if (error instanceof Error) {
          makeToast.danger(t('departmentsTab.editError'), error.message);
        }
      }
    }
  };

  const handleCancelAdd = () => {
    setIsAddingNewDepartment(false);
    setDepartmentToEdit(undefined);
    reset();
  };

  if (loading) return <Box padding={30}>Loading.....</Box>;
  if (error || !data?.me?.departments) return <Box padding={30}>Something went wrong!</Box>;

  return (
    <>
      <Box marginTop={8} display="flex" flexDirection="column" gap={3}>
        <Box width="8/12" marginBottom={5}>
          <Text variant="pMediumRegular">
            <Trans i18nKey="stillingar:departmentsTab.pageCopy">
              ..
              <strong>{{ name }}</strong>
              ...
            </Trans>
          </Text>
        </Box>
        <Box
          display="flex"
          justifyContent="space-between"
          flexDirection={['column', 'column', 'row']}
          gap={[6, 6, 3]}
        >
          <Box width={['100%', '100%', '6/12']}>
            <Input
              id="searchInput"
              name="searchInput"
              label={t('departmentsTab.searchPlaceholder')}
              icon="search"
              color="grey900"
              defaultValue={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
            />
          </Box>
          <Box width={['100%', '100%', '4/12']} alignSelf="flex-end" marginBottom={3}>
            <MainButton
              text={t('departmentsTab.addButton')}
              dottedShadow="none"
              colorScheme="white"
              icon="add"
              onClick={() => setIsAddingNewDepartment(true)}
            />
          </Box>
        </Box>
      </Box>
      <Box display="flex" flexDirection="column">
        <Text variant="pMediumBold" marginBottom={5} marginTop={7}>
          {t('departmentsTab.tableSectionTitle')}
        </Text>
        <Box paddingX={3}>
          {(!!data?.me?.departments?.length || isAddingNewDepartment) && (
            <Grid gridTemplate={{ sm: 4, lg: 12 }} rowGap={[2, 2, 4]} alignItems="center">
              <GridItem gridColumn={{ sm: 'span2', lg: 'span9' }}>
                <Text>{t('departmentsTab.th1')}</Text>
              </GridItem>
              <GridItem gridColumn={{ sm: 'span2', lg: 'span3' }}>
                <Box width="100%" display="flex" justifyContent="flex-end">
                  <Text>{t('departmentsTab.th3')}</Text>
                </Box>
              </GridItem>
            </Grid>
          )}
        </Box>
        {isAddingNewDepartment && !departmentToEdit && (
          <Box padding={3} marginY={2}>
            <Grid>
              <EditableRow
                control={control}
                setValue={setValue}
                onSaveClick={() => handleSubmit()}
                onCancelClick={() => handleCancelAdd()}
              />
            </Grid>
          </Box>
        )}
        {data?.me?.departments
          ?.filter(
            (department) =>
              department?.name?.toLowerCase().includes(searchTerm?.toLocaleLowerCase() ?? ''),
          )
          .map((department) => {
            if (!department) return null;
            return (
              <Box key={department.id} background="white" padding={3} marginY={2}>
                <Grid
                  gridTemplate={{ sm: 4, md: 4, lg: 12 }}
                  rowGap={[2, 2, 4]}
                  alignItems="center"
                >
                  {!!departmentToEdit && departmentToEdit.name === department.name ? (
                    <EditableRow
                      control={control}
                      setValue={setValue}
                      defaultValue={departmentToEdit.name ?? ''}
                      onSaveClick={() => handleSubmit()}
                      onCancelClick={() => handleCancelAdd()}
                    />
                  ) : (
                    <>
                      <GridItem gridColumn={{ sm: 'span2', md: 'span2', lg: 'span9' }}>
                        <Text variant="pMediumBold">{department.name}</Text>
                      </GridItem>

                      <GridItem gridColumn={{ sm: 'span2', md: 'span2', lg: 'span3' }}>
                        <Box width="100%" display="flex" justifyContent="flex-end">
                          <Menu
                            color="pink"
                            label={`Edit menu for ${department.name}`}
                            items={[
                              {
                                text: t('departmentsTab.edit'),
                                onClick: () => handleEditDepartment(department),
                              },
                              {
                                text: t('departmentsTab.delete'),
                                onClick: () => setDepartmentToDelete(department),
                              },
                            ]}
                            disclosure={
                              <IconButton
                                color="black100"
                                icon="dotsHorizontal"
                                hiddenButtonText="More button"
                              />
                            }
                          />
                        </Box>
                      </GridItem>
                    </>
                  )}
                </Grid>
              </Box>
            );
          })}
      </Box>
      <ConfirmDeleteModal
        isVisible={!!departmentToDelete}
        translateKey="department"
        name={departmentToDelete?.name ?? ''}
        onVisibilityChange={(isVisible) =>
          !isVisible ? setDepartmentToDelete(undefined) : setDepartmentToDelete(departmentToDelete)
        }
        onClose={() => {
          setDepartmentToDelete(undefined);
        }}
        onDelete={() => handleDeleteDepartment()}
      />
    </>
  );
};
