import _extends from "@babel/runtime/helpers/esm/extends";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
var _excluded = ["render", "renderWithProps", "values", "componentFamily", "emptyValue", "assertRenderedValue", "setNewValue", "clock"];
import * as React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { screen, act, userEvent } from '@mui/monorepo/test/utils';
import { inputBaseClasses } from '@mui/material/InputBase';
import { getExpectedOnChangeCount } from 'test/utils/pickers';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
export var testControlledUnControlled = function testControlledUnControlled(ElementToTest, options) {
  var render = options.render,
    renderWithProps = options.renderWithProps,
    values = options.values,
    componentFamily = options.componentFamily,
    emptyValue = options.emptyValue,
    assertRenderedValue = options.assertRenderedValue,
    setNewValue = options.setNewValue,
    clock = options.clock,
    pickerParams = _objectWithoutProperties(options, _excluded);
  var params = pickerParams;
  describe('Controlled / uncontrolled value', function () {
    it('should render `props.defaultValue` if no `props.value` is passed', function () {
      render( /*#__PURE__*/_jsx(ElementToTest, {
        defaultValue: values[0]
      }));
      assertRenderedValue(values[0]);
    });
    it('should render `props.value` if passed', function () {
      render( /*#__PURE__*/_jsx(ElementToTest, {
        value: values[0]
      }));
      assertRenderedValue(values[0]);
    });
    it('should render `props.value` if both `props.defaultValue` and `props.value` are passed', function () {
      render( /*#__PURE__*/_jsx(ElementToTest, {
        defaultValue: values[0],
        value: values[1]
      }));
      assertRenderedValue(values[1]);
    });
    it('should render nothing if neither `props.defaultValue` or `props.value` are passed', function () {
      render( /*#__PURE__*/_jsx(ElementToTest, {}));
      assertRenderedValue(emptyValue);
    });
    it('should call onChange when updating a value defined with `props.defaultValue` and update the rendered value', function () {
      var onChange = spy();
      var _renderWithProps = renderWithProps({
          defaultValue: values[0],
          onChange: onChange
        }),
        selectSection = _renderWithProps.selectSection;
      var newValue = setNewValue(values[0], {
        selectSection: selectSection
      });
      assertRenderedValue(newValue);
      // TODO: Clean this exception or change the clock behavior
      expect(onChange.callCount).to.equal(getExpectedOnChangeCount(componentFamily, params));
      if (Array.isArray(newValue)) {
        newValue.forEach(function (value, index) {
          expect(onChange.lastCall.args[0][index]).toEqualDateTime(value);
        });
      } else {
        expect(onChange.lastCall.args[0]).toEqualDateTime(newValue);
      }
    });
    it('should call onChange when updating a value defined with `props.value`', function () {
      var onChange = spy();
      var useControlledElement = function useControlledElement(props) {
        var _React$useState = React.useState((props == null ? void 0 : props.value) || null),
          _React$useState2 = _slicedToArray(_React$useState, 2),
          value = _React$useState2[0],
          setValue = _React$useState2[1];
        var handleChange = React.useCallback(function (newValue) {
          setValue(newValue);
          props == null || props.onChange(newValue);
        }, [props]);
        return {
          value: value,
          onChange: handleChange
        };
      };
      var _renderWithProps2 = renderWithProps({
          value: values[0],
          onChange: onChange
        }, useControlledElement),
        selectSection = _renderWithProps2.selectSection;
      var newValue = setNewValue(values[0], {
        selectSection: selectSection
      });
      expect(onChange.callCount).to.equal(getExpectedOnChangeCount(componentFamily, params));
      if (Array.isArray(newValue)) {
        newValue.forEach(function (value, index) {
          expect(onChange.lastCall.args[0][index]).toEqualDateTime(value);
        });
      } else {
        expect(onChange.lastCall.args[0]).toEqualDateTime(newValue);
      }
    });
    it('should react to `props.value` update', function () {
      var _render = render( /*#__PURE__*/_jsx(ElementToTest, {
          value: values[0]
        })),
        setProps = _render.setProps;
      setProps({
        value: values[1]
      });
      assertRenderedValue(values[1]);
    });
    ['readOnly', 'disabled'].forEach(function (prop) {
      it("should apply ".concat(prop, "=\"true\" prop"), function () {
        if (!['field', 'picker'].includes(componentFamily)) {
          return;
        }
        var handleChange = spy();
        render( /*#__PURE__*/_jsx(ElementToTest, _extends({
          value: values[0],
          onChange: handleChange
        }, _defineProperty({}, prop, true))));
        var textBoxes = screen.getAllByRole('textbox');
        textBoxes.forEach(function (textbox) {
          expect(textbox).to.have.attribute(prop.toLowerCase());
        });
      });
    });
    it('should not allow editing with keyboard in mobile pickers', function () {
      if (componentFamily !== 'picker' || params.variant !== 'mobile') {
        return;
      }
      var handleChange = spy();
      render( /*#__PURE__*/_jsx(ElementToTest, {
        defaultValue: values[0],
        onChange: handleChange
      }));
      var input = screen.getAllByRole('textbox')[0];
      act(function () {
        input.focus();
      });
      clock.runToLast();
      userEvent.keyPress(input, {
        key: 'ArrowUp'
      });
      clock.runToLast();
      expect(handleChange.callCount).to.equal(0);
    });
    it('should have correct labelledby relationship when toolbar is shown', function () {
      if (componentFamily !== 'picker' || params.variant === 'desktop' && params.type === 'date-range') {
        return;
      }
      render( /*#__PURE__*/_jsx(ElementToTest, {
        open: true,
        slotProps: {
          toolbar: {
            hidden: false
          }
        },
        localeText: {
          toolbarTitle: 'Test toolbar'
        }
      }));
      expect(screen.getByLabelText('Test toolbar')).to.have.attribute('role', 'dialog');
    });
    it('should have correct labelledby relationship with provided label when toolbar is hidden', function () {
      if (componentFamily !== 'picker' || params.variant === 'desktop' && params.type === 'date-range') {
        return;
      }
      render( /*#__PURE__*/_jsx(ElementToTest, _extends({
        open: true
      }, params.type === 'date-range' ? {
        localeText: {
          start: 'test',
          end: 'relationship'
        }
      } : {
        label: 'test relationship'
      }, {
        slotProps: {
          toolbar: {
            hidden: true
          }
        }
      })));
      expect(screen.getByLabelText('test relationship', {
        selector: 'div'
      })).to.have.attribute('role', 'dialog');
    });
    it('should have correct labelledby relationship without label and hidden toolbar but external props', function () {
      if (componentFamily !== 'picker' || params.variant === 'desktop' && params.type === 'date-range') {
        return;
      }
      render( /*#__PURE__*/_jsxs("div", {
        children: [/*#__PURE__*/_jsx("div", {
          id: "label-id",
          children: "external label"
        }), /*#__PURE__*/_jsx(ElementToTest, _extends({
          open: true
        }, params.type === 'date-range' && {
          localeText: {
            start: '',
            end: ''
          }
        }, {
          slotProps: _defineProperty({
            toolbar: {
              hidden: true
            }
          }, params.variant === 'desktop' ? 'popper' : 'mobilePaper', {
            'aria-labelledby': 'label-id'
          })
        }))]
      }));
      expect(screen.getByLabelText('external label')).to.have.attribute('role', 'dialog');
    });
    describe('slots: textField', function () {
      it('should respect provided `error="true"` prop', function () {
        if (!['field', 'picker'].includes(componentFamily)) {
          return;
        }
        render( /*#__PURE__*/_jsx(ElementToTest, {
          slotProps: {
            textField: {
              error: true
            }
          }
        }));
        var textBoxes = screen.getAllByRole('textbox');
        textBoxes.forEach(function (textbox) {
          expect(textbox.parentElement).to.have.class(inputBaseClasses.error);
          expect(textbox).to.have.attribute('aria-invalid', 'true');
        });
      });
    });
  });
};