import { useEffect, useMemo } from 'react';
import { useSelector } from 'react-redux';
import {
  Box,
  Button,
  Checkbox,
  Chip,
  CircularProgress,
  FormControl,
  FormControlLabel,
  FormLabel,
  ListItemText,
  MenuItem,
  Select,
  TextField
} from '@mui/material';
import { Controller, useForm } from 'react-hook-form';
import validator from 'validator';

import Dialog from '../Dialog';
import {
  fetchProfileSettings,
  fetchTreeMetadata,
  selectProfileSettings,
  selectTreeLoadingStates,
  selectTreeMetadata,
  selectTreeMetadataLoaded,
  updateProfileSettings
} from './store';
import { useHostTreeDispatch } from './store/dispatchType';
import { NAME_PATTERN } from './constants';

interface FormValues {
  name: string;
  sharedPermission: string[];
  global: boolean;
}

interface Props {
  open: boolean;
  profileId: number | string | null;
  existingNames: string[]; // for duplicate-name validation (excluding self)
  onClose: () => void;
  onSaved: () => void;
}

export const EditProfileDialog = ({
  open,
  profileId,
  existingNames,
  onClose,
  onSaved
}: Props) => {
  const dispatch = useHostTreeDispatch();
  const settingsSelector = useMemo(() => selectProfileSettings(profileId), [profileId]);
  const original = useSelector(settingsSelector);
  const treeMetadata = useSelector(selectTreeMetadata);
  const treeMetadataLoaded = useSelector(selectTreeMetadataLoaded);
  const { updateProfileSettings: submitting } = useSelector(selectTreeLoadingStates);

  const roles = treeMetadata?.roles ?? [];
  const isAdmin = treeMetadata?.isAdmin ?? false;

  const {
    control,
    handleSubmit,
    reset,
    setError,
    formState: { errors }
  } = useForm<FormValues>({
    defaultValues: { name: '', sharedPermission: [], global: false },
    mode: 'onTouched'
  });

  // Fetch on open
  useEffect(() => {
    if (!open || profileId === null) return;
    dispatch(fetchProfileSettings(profileId));
    if (!treeMetadataLoaded) dispatch(fetchTreeMetadata());
  }, [dispatch, open, profileId, treeMetadataLoaded]);

  // Seed form when settings arrive
  useEffect(() => {
    if (!open || !original) return;
    reset({
      name: original.name,
      sharedPermission: original.sharedPermission ?? [],
      global: !!original.globalTree
    });
  }, [open, original, reset]);

  const validateName = (value: string): string | true => {
    const trimmed = value.trim();
    if (validator.isEmpty(trimmed)) return 'Name cannot be empty';
    if (!validator.matches(trimmed, NAME_PATTERN)) {
      return 'Name can only contain alphanumeric characters, spaces, "_" or "-" (max 100 characters)';
    }
    if (
      original &&
      trimmed.toLowerCase() !== original.name.toLowerCase() &&
      existingNames.some(n => n.toLowerCase() === trimmed.toLowerCase())
    ) {
      return 'Tree already exists, please choose a different name';
    }
    return true;
  };

  const submit = handleSubmit(async values => {
    if (profileId === null) return;
    const action = await dispatch(
      updateProfileSettings({
        id: profileId,
        newname: values.name.trim(),
        sharedPermission: values.sharedPermission,
        globalTree: values.global
      })
    );
    if (updateProfileSettings.fulfilled.match(action)) {
      onSaved();
    } else {
      setError('root', { message: (action.error?.message as string) ?? 'Failed to update tree' });
    }
  });

  const loading = open && profileId !== null && !original;

  return (
    <Dialog
      open={open}
      onClose={onClose}
      title="Edit tree"
      size="sm"
      fullWidth
      actionButtons={
        <>
          <Button onClick={onClose} variant="outlined" color="inherit">
            Cancel
          </Button>
          <Button
            onClick={submit}
            variant="contained"
            color="primary"
            disabled={submitting || loading}
          >
            Ok
          </Button>
        </>
      }
    >
      {loading ? (
        <Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
          <CircularProgress size={24} />
        </Box>
      ) : (
        <form onSubmit={submit}>
          {errors.root && <div className="alert alert-error">{errors.root.message}</div>}

          <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2, mb: 2 }}>
            <FormLabel htmlFor="hosts-tree-edit-name" sx={{ width: 200, flexShrink: 0, mt: 1 }}>
              Title
            </FormLabel>
            <Controller
              name="name"
              control={control}
              rules={{ validate: validateName }}
              render={({ field, fieldState }) => (
                <TextField
                  {...field}
                  id="hosts-tree-edit-name"
                  autoFocus
                  fullWidth
                  size="small"
                  error={!!fieldState.error}
                  helperText={fieldState.error?.message}
                />
              )}
            />
          </Box>

          <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>
            <FormLabel sx={{ width: 200, flexShrink: 0, mt: 1 }}>
              Share categorization with these user roles
            </FormLabel>
            <Controller
              name="sharedPermission"
              control={control}
              render={({ field }) => (
                <FormControl size="small" fullWidth>
                  <Select
                    multiple
                    value={field.value}
                    onChange={e => {
                      const v = e.target.value;
                      field.onChange(typeof v === 'string' ? v.split(',') : v);
                    }}
                    displayEmpty
                    renderValue={selected =>
                      (selected as string[]).length === 0 ? (
                        <em style={{ color: '#999' }}>None selected</em>
                      ) : (
                        <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
                          {(selected as string[]).map(r => (
                            <Chip key={r} label={r} size="small" />
                          ))}
                        </Box>
                      )
                    }
                  >
                    {roles.length === 0 ? (
                      <MenuItem disabled>(no roles available)</MenuItem>
                    ) : (
                      roles.map(r => (
                        <MenuItem key={r} value={r}>
                          <Checkbox checked={field.value.indexOf(r) > -1} />
                          <ListItemText primary={r} />
                        </MenuItem>
                      ))
                    )}
                  </Select>
                </FormControl>
              )}
            />
          </Box>

          {isAdmin && (
            <Box sx={{ mt: 2 }}>
              <Controller
                name="global"
                control={control}
                render={({ field }) => (
                  <FormControlLabel
                    control={<Checkbox checked={field.value} onChange={e => field.onChange(e.target.checked)} />}
                    label="Add this categorization to all users' accounts"
                  />
                )}
              />
            </Box>
          )}
        </form>
      )}
    </Dialog>
  );
};
