import { useState } from 'react';

import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close';
import EditIcon from '@mui/icons-material/Edit';
import { Box, ButtonBase, ClickAwayListener, IconButton, InputBase, type Theme } from '@mui/material';

import { darkBlue, gray } from '../../themes/common';

interface EditableFieldProps {
  maxLength?: number;
  onSave: (value: string) => Promise<unknown> | void;
  value: string;
}

// Reusable inline "click to edit" field: display mode shows a pencil badge on
// hover; clicking enters edit mode, committed on ✓ / Enter / click-away, reverted on ✗ / Escape.

const displaySx = (theme: Theme) => ({
  border: '1px solid transparent',
  borderRadius: '4px',
  cursor: 'text',
  display: 'inline-block',
  font: 'inherit',
  ml: '-12px',
  padding: '8px 70px 8px 12px',
  position: 'relative',
  textAlign: 'left',
  '&:hover, &:focus-visible': {
    borderColor: theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.12)' : gray[200],
    '& .editable-pencil': { display: 'flex' }
  }
});

const editSx = {
  alignItems: 'center',
  border: `1px solid ${darkBlue[600]}`,
  borderRadius: '4px',
  display: 'inline-flex',
  maxWidth: '100%',
  ml: '-12px',
  padding: '8px 10px 8px 12px',
  width: 768
} as const;

// The gray badge/buttons keep a dark glyph in both themes.
const pencilSx = {
  alignItems: 'center',
  backgroundColor: gray[200],
  borderRadius: '0 4px 4px 0',
  bottom: 0,
  color: gray[600],
  display: 'none',
  justifyContent: 'center',
  position: 'absolute',
  right: 0,
  top: 0,
  width: 48
} as const;

const buttonSx = {
  backgroundColor: gray[200],
  borderRadius: '4px',
  color: gray[600],
  flexShrink: 0,
  height: 26,
  ml: '6px',
  p: 0,
  width: 26,
  '&:hover': { backgroundColor: gray[200] }
} as const;

export const EditableField = ({ value, maxLength, onSave }: EditableFieldProps) => {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value);

  const startEditing = () => {
    setDraft(value);
    setEditing(true);
  };

  const cancel = () => setEditing(false);

  const commit = () => {
    setEditing(false);
    const next = draft.trim();
    if (next && next !== value) onSave(next);
  };

  if (!editing) {
    return (
      <ButtonBase data-testid="editable-field" aria-label={`Edit ${value}`} sx={displaySx} onClick={startEditing}>
        {value}
        <Box className="editable-pencil" component="span" sx={pencilSx}>
          <EditIcon fontSize="small" />
        </Box>
      </ButtonBase>
    );
  }

  return (
    <ClickAwayListener onClickAway={commit}>
      <Box sx={editSx}>
        <InputBase
          value={draft}
          autoFocus
          inputProps={{ maxLength, 'aria-label': 'Name' }}
          sx={{
            color: 'inherit',
            flexGrow: 1,
            font: 'inherit',
            letterSpacing: 'inherit',
            '& .MuiInputBase-input': {
              background: 'none',
              border: 'none',
              boxShadow: 'none',
              color: 'inherit',
              font: 'inherit',
              height: 'auto',
              letterSpacing: 'inherit',
              mb: 0,
              p: 0,
              '&:focus': { background: 'none', border: 'none', boxShadow: 'none' }
            }
          }}
          onChange={event => setDraft(event.target.value)}
          onFocus={event => event.target.select()}
          onKeyDown={event => {
            if (event.key === 'Enter') {
              event.preventDefault();
              commit();
            } else if (event.key === 'Escape') {
              cancel();
            }
          }}
        />
        <IconButton aria-label="Save" size="small" sx={buttonSx} onClick={commit}>
          <CheckIcon fontSize="small" />
        </IconButton>
        <IconButton aria-label="Cancel" size="small" sx={buttonSx} onClick={cancel}>
          <CloseIcon fontSize="small" />
        </IconButton>
      </Box>
    </ClickAwayListener>
  );
};
