// Copyright 2023 Northern.tech AS
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
import { useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';

import { Button, Typography, alpha } from '@mui/material';
import { makeStyles } from 'tss-react/mui';

import { TIMEOUTS } from '@northern.tech/store/constants';
import { isDarkMode } from '@northern.tech/store/utils';
import { useDebounce } from '@northern.tech/utils/debouncehook';

const useStyles = makeStyles()(theme => ({
  container: {
    backgroundColor: isDarkMode(theme.palette.mode) ? theme.palette.info.main : alpha(theme.palette.info.main, theme.palette.action.selectedOpacity),
    padding: `10px ${theme.spacing(3)} ${theme.spacing(3)}`
  },
  filters: {
    columnGap: theme.spacing(2),
    display: 'flex',
    flexWrap: 'wrap',
    rowGap: theme.spacing(2),
    '.filter-item': {
      display: 'grid',
      gridTemplateRows: 'minmax(50px, max-content) 1fr'
    }
  },
  filterReset: {
    marginBottom: 2,
    marginTop: 2
  }
}));

export const Filters = ({ className = '', defaultValues, filters = [], initialValues, onChange, fieldResetTrigger = '', dirtyField, clearDirty }) => {
  const { classes } = useStyles();
  const [values, setValues] = useState(initialValues);

  const methods = useForm({ mode: 'onChange', defaultValues });
  const { formState, reset, resetField, watch, setValue, getValues } = methods;
  const { isDirty } = formState;

  useEffect(() => {
    Object.entries(initialValues).forEach(([key, value]) => setValue(key, value));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [JSON.stringify(initialValues), setValue]);

  useEffect(() => {
    if (dirtyField && !formState.isDirty) {
      setValue(dirtyField, getValues(dirtyField), { shouldDirty: true });
      clearDirty('');
    }
  }, [clearDirty, dirtyField, formState, getValues, setValue]);

  useEffect(() => {
    if (!fieldResetTrigger) {
      return;
    }
    resetField(fieldResetTrigger);
  }, [fieldResetTrigger, resetField]);

  watch(setValues);
  const debouncedValues = useDebounce(values, TIMEOUTS.oneSecond);

  useEffect(() => {
    onChange(debouncedValues);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [JSON.stringify(debouncedValues), onChange]);

  return (
    <FormProvider {...methods}>
      <form className={`margin-bottom margin-top flexbox space-between ${classes.container} ${className}`} noValidate>
        <div className={classes.filters}>
          {filters.map(({ key, title, Component, componentProps }) => (
            <div className="filter-item" key={key}>
              <Typography className="margin-top-small margin-bottom-small" color="textSecondary" variant="subtitle2">
                {title}
              </Typography>
              <Component name={key} {...componentProps} />
            </div>
          ))}
        </div>
        {isDirty && (
          <div>
            <Typography className="margin-top-small margin-bottom-small" color="textSecondary" variant="subtitle2">{`\u{200B}`}</Typography>
            <Button className={`nowrap ${classes.filterReset}`} color="info" onClick={() => reset()} variant="outlined">
              Clear filter
            </Button>
          </div>
        )}
      </form>
    </FormProvider>
  );
};

export default Filters;
