import { useEffect, useState } from 'react';
import { Box, Button, FormLabel, IconButton, TextField } from '@mui/material';
import VisibilityIcon from '@mui/icons-material/Visibility';
import { Controller, useForm } from 'react-hook-form';
import validator from 'validator';

import Dialog from '../Dialog';
import { ClassFinderDialog } from './ClassFinderDialog';
import { NAME_PATTERN } from './constants';

const MAX_INPUT_WIDTH = 200;

const isValidClassExpression = (expr: string): boolean => {
  try {
    new RegExp(expr);
    return true;
  } catch {
    return false;
  }
};

export type NodeFormMode = 'Add' | 'Update';

interface FormValues {
  label: string;
  classRegex: string;
}

interface Props {
  open: boolean;
  mode: NodeFormMode;
  initialLabel?: string;
  initialClassRegex?: string;
  onClose: () => void;
  onSubmit: (values: { label: string; classRegex: string }) => Promise<void> | void;
}

export const NodeFormDialog = ({
  open,
  mode,
  initialLabel = '',
  initialClassRegex = '',
  onClose,
  onSubmit
}: Props) => {
  const {
    control,
    handleSubmit,
    reset,
    setValue,
    getValues,
    formState: { isSubmitting }
  } = useForm<FormValues>({
    defaultValues: { label: initialLabel, classRegex: initialClassRegex },
    mode: 'onTouched'
  });

  const [classFinderOpen, setClassFinderOpen] = useState(false);

  const handlePickClass = (cls: string) => {
    // Append the chosen class to the existing expression with `|` (alternation),
    // matching the NewProfileDialog behaviour.
    const current = getValues('classRegex').trim();
    setValue('classRegex', current ? `${current}|${cls}` : cls, { shouldValidate: true });
  };

  // reset fields whenever the dialog is (re)opened for a different node
  useEffect(() => {
    if (open) reset({ label: initialLabel, classRegex: initialClassRegex });
  }, [open, initialLabel, initialClassRegex, reset]);

  const submit = handleSubmit(async values => {
    await onSubmit({ label: values.label.trim(), classRegex: values.classRegex.trim() });
  });

  return (
    <Dialog
      open={open}
      onClose={onClose}
      title={mode === 'Update' ? 'Edit sub-category' : 'Add new sub-category'}
      size="sm"
      fullWidth
      actionButtons={
        <>
          <Button onClick={onClose} variant="outlined" color="inherit">
            Cancel
          </Button>
          <Button
            onClick={submit}
            variant="contained"
            color="primary"
            disabled={isSubmitting}
          >
            {mode}
          </Button>
        </>
      }
    >
      <form onSubmit={submit}>
        <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2, mb: 2 }}>
          <FormLabel htmlFor="hosts-tree-node-label" sx={{ width: 200, flexShrink: 0, mt: 1 }}>
            Label
          </FormLabel>
          <Controller
            name="label"
            control={control}
            rules={{
              validate: value => {
                if (validator.isEmpty(value, { ignore_whitespace: true })) {
                  return 'Label cannot be empty';
                }
                if (!validator.matches(value, NAME_PATTERN)) {
                  return 'Label can only contain alphanumeric characters, spaces, "_" or "-" (max 100 characters)';
                }
                return true;
              }
            }}
            render={({ field, fieldState }) => (
              <TextField
                {...field}
                id="hosts-tree-node-label"
                autoFocus
                size="small"
                sx={{ maxWidth: MAX_INPUT_WIDTH, width: '100%' }}
                error={!!fieldState.error}
                helperText={fieldState.error?.message}
              />
            )}
          />
        </Box>

        <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>
          <FormLabel htmlFor="hosts-tree-node-class" sx={{ width: 200, flexShrink: 0, mt: 1 }}>
            CFEngine class expression (.*+[])
          </FormLabel>
          <Controller
            name="classRegex"
            control={control}
            rules={{
              validate: value => {
                if (validator.isEmpty(value, { ignore_whitespace: true })) {
                  return 'Class expression cannot be empty';
                }
                if (!isValidClassExpression(value)) {
                  return 'Invalid class expression';
                }
                return true;
              }
            }}
            render={({ field, fieldState }) => (
              <TextField
                {...field}
                id="hosts-tree-node-class"
                size="small"
                sx={{ maxWidth: MAX_INPUT_WIDTH, width: '100%' }}
                error={!!fieldState.error}
                helperText={fieldState.error?.message}
              />
            )}
          />
          <IconButton
            aria-label="Find class"
            title="Select a class"
            onClick={() => setClassFinderOpen(true)}
            sx={{ mt: 0.5 }}
          >
            <VisibilityIcon />
          </IconButton>
        </Box>
      </form>

      <ClassFinderDialog
        open={classFinderOpen}
        onClose={() => setClassFinderOpen(false)}
        onSelect={handlePickClass}
      />
    </Dialog>
  );
};
