// @eslint-react rules
// see: https://eslint-react.xyz/docs/rules

export default {
  // Enforce that class methods utilize this
  // https://eslint.org/docs/rules/class-methods-use-this
  'class-methods-use-this': [
    'error',
    {
      exceptMethods: [
        'UNSAFE_componentWillMount',
        'UNSAFE_componentWillReceiveProps',
        'UNSAFE_componentWillUpdate',
        'componentDidCatch',
        'componentDidMount',
        'componentDidUpdate',
        'componentWillMount',
        'componentWillReceiveProps',
        'componentWillUnmount',
        'componentWillUpdate',
        'getChildContext',
        'getDefaultProps',
        'getInitialState',
        'getSnapshotBeforeUpdate',
        'render',
        'shouldComponentUpdate',
      ],
    },
  ],

  // --- Core React rules ---

  // Validates higher order functions defining nested components or hooks
  // https://eslint-react.xyz/docs/rules/component-hook-factories
  '@eslint-react/component-hook-factories': 'error',

  // Validates usage of Error Boundaries instead of try/catch for child errors
  // https://eslint-react.xyz/docs/rules/error-boundaries
  '@eslint-react/error-boundaries': 'error',

  // Verify the list of the dependencies for Hooks like useEffect and similar
  // https://eslint-react.xyz/docs/rules/exhaustive-deps
  '@eslint-react/exhaustive-deps': 'error',

  // Validates against mutating props, state, and other immutable values
  // https://eslint-react.xyz/docs/rules/immutability
  '@eslint-react/immutability': 'error',

  // Prevent using this.state within a this.setState
  // https://eslint-react.xyz/docs/rules/no-access-state-in-setstate
  '@eslint-react/no-access-state-in-setstate': 'error',

  // Prevent usage of Array index in keys
  // https://eslint-react.xyz/docs/rules/no-array-index-key
  '@eslint-react/no-array-index-key': 'error',

  // Disallow usage of Children.count
  // https://eslint-react.xyz/docs/rules/no-children-count
  '@eslint-react/no-children-count': 'error',

  // Disallow usage of Children.forEach
  // https://eslint-react.xyz/docs/rules/no-children-for-each
  '@eslint-react/no-children-for-each': 'error',

  // Disallow usage of Children.map
  // https://eslint-react.xyz/docs/rules/no-children-map
  '@eslint-react/no-children-map': 'error',

  // Disallow usage of Children.only
  // https://eslint-react.xyz/docs/rules/no-children-only
  '@eslint-react/no-children-only': 'error',

  // Disallow usage of Children.toArray
  // https://eslint-react.xyz/docs/rules/no-children-to-array
  '@eslint-react/no-children-to-array': 'error',

  // Disallow class components (except for error boundaries)
  // https://eslint-react.xyz/docs/rules/no-class-component
  '@eslint-react/no-class-component': 'error',

  // Disallow usage of cloneElement
  // https://eslint-react.xyz/docs/rules/no-clone-element
  '@eslint-react/no-clone-element': 'error',

  // Disallow usage of componentWillMount
  // https://eslint-react.xyz/docs/rules/no-component-will-mount
  '@eslint-react/no-component-will-mount': 'error',

  // Disallow usage of componentWillReceiveProps
  // https://eslint-react.xyz/docs/rules/no-component-will-receive-props
  '@eslint-react/no-component-will-receive-props': 'error',

  // Disallow usage of componentWillUpdate
  // https://eslint-react.xyz/docs/rules/no-component-will-update
  '@eslint-react/no-component-will-update': 'error',

  // Disallow usage of legacy Context.Provider (React 19+)
  // https://eslint-react.xyz/docs/rules/no-context-provider
  '@eslint-react/no-context-provider': 'error',

  // Disallow usage of createRef (prefer useRef)
  // https://eslint-react.xyz/docs/rules/no-create-ref
  '@eslint-react/no-create-ref': 'error',

  // Prevent direct mutation of this.state
  // https://eslint-react.xyz/docs/rules/no-direct-mutation-state
  '@eslint-react/no-direct-mutation-state': 'error',

  // Disallow duplicate keys in JSX arrays
  // https://eslint-react.xyz/docs/rules/no-duplicate-key
  '@eslint-react/no-duplicate-key': 'error',

  // Disallow usage of forwardRef (React 19+ passes ref as prop)
  // https://eslint-react.xyz/docs/rules/no-forward-ref
  '@eslint-react/no-forward-ref': 'error',

  // Prevent implicitly passing the children prop
  // https://eslint-react.xyz/docs/rules/no-implicit-children
  '@eslint-react/no-implicit-children': 'error',

  // Prevent implicitly passing the key prop
  // https://eslint-react.xyz/docs/rules/no-implicit-key
  '@eslint-react/no-implicit-key': 'error',

  // Prevent implicitly passing the ref prop
  // https://eslint-react.xyz/docs/rules/no-implicit-ref
  '@eslint-react/no-implicit-ref': 'error',

  // Prevent problematic leaked values from being rendered
  // https://eslint-react.xyz/docs/rules/no-leaked-conditional-rendering
  '@eslint-react/no-leaked-conditional-rendering': 'error',

  // Enforce that components have a displayName for DevTools
  // https://eslint-react.xyz/docs/rules/no-missing-component-display-name
  '@eslint-react/no-missing-component-display-name': 'off',

  // Enforce that contexts have a displayName for DevTools
  // https://eslint-react.xyz/docs/rules/no-missing-context-display-name
  '@eslint-react/no-missing-context-display-name': 'off',

  // Enforce that every JSX element in a list has a key prop
  // https://eslint-react.xyz/docs/rules/no-missing-key
  '@eslint-react/no-missing-key': 'error',

  // Disallow misusing captureOwnerStack
  // https://eslint-react.xyz/docs/rules/no-misused-capture-owner-stack
  '@eslint-react/no-misused-capture-owner-stack': 'error',

  // Prevent creating unstable components inside components
  // https://eslint-react.xyz/docs/rules/no-nested-component-definitions
  '@eslint-react/no-nested-component-definitions': 'error',

  // Prevent creating lazy components inside components
  // https://eslint-react.xyz/docs/rules/no-nested-lazy-component-declarations
  '@eslint-react/no-nested-lazy-component-declarations': 'error',

  // Prevent usage of shouldComponentUpdate when extending React.PureComponent
  // https://eslint-react.xyz/docs/rules/no-redundant-should-component-update
  '@eslint-react/no-redundant-should-component-update': 'error',

  // Prevent usage of setState in componentDidMount
  // https://eslint-react.xyz/docs/rules/no-set-state-in-component-did-mount
  '@eslint-react/no-set-state-in-component-did-mount': 'error',

  // Prevent usage of setState in componentDidUpdate
  // https://eslint-react.xyz/docs/rules/no-set-state-in-component-did-update
  '@eslint-react/no-set-state-in-component-did-update': 'error',

  // Prevent usage of setState in componentWillUpdate
  // https://eslint-react.xyz/docs/rules/no-set-state-in-component-will-update
  '@eslint-react/no-set-state-in-component-will-update': 'error',

  // Disallow unnecessary useCallback hooks
  // https://eslint-react.xyz/docs/rules/no-unnecessary-use-callback
  '@eslint-react/no-unnecessary-use-callback': 'error',

  // Disallow unnecessary useMemo hooks
  // https://eslint-react.xyz/docs/rules/no-unnecessary-use-memo
  '@eslint-react/no-unnecessary-use-memo': 'error',

  // Disallow unnecessary "use" prefix on custom hooks
  // https://eslint-react.xyz/docs/rules/no-unnecessary-use-prefix
  '@eslint-react/no-unnecessary-use-prefix': 'error',

  // Disallow usage of UNSAFE_componentWillMount
  // https://eslint-react.xyz/docs/rules/no-unsafe-component-will-mount
  '@eslint-react/no-unsafe-component-will-mount': 'error',

  // Disallow usage of UNSAFE_componentWillReceiveProps
  // https://eslint-react.xyz/docs/rules/no-unsafe-component-will-receive-props
  '@eslint-react/no-unsafe-component-will-receive-props': 'error',

  // Disallow usage of UNSAFE_componentWillUpdate
  // https://eslint-react.xyz/docs/rules/no-unsafe-component-will-update
  '@eslint-react/no-unsafe-component-will-update': 'error',

  // Prevent non-stable values used as context values
  // https://eslint-react.xyz/docs/rules/no-unstable-context-value
  '@eslint-react/no-unstable-context-value': 'error',

  // Disallow referential-type variables as default props
  // https://eslint-react.xyz/docs/rules/no-unstable-default-props
  '@eslint-react/no-unstable-default-props': 'error',

  // Prevent declaring unused methods of component class
  // https://eslint-react.xyz/docs/rules/no-unused-class-component-members
  '@eslint-react/no-unused-class-component-members': 'error',

  // Warn about component props that are defined but never used
  // https://eslint-react.xyz/docs/rules/no-unused-props
  '@eslint-react/no-unused-props': 'error',

  // Prevent unused state values
  // https://eslint-react.xyz/docs/rules/no-unused-state
  '@eslint-react/no-unused-state': 'error',

  // Prefer using use() over useContext() (React 19+)
  // https://eslint-react.xyz/docs/rules/no-use-context
  '@eslint-react/no-use-context': 'error',

  // Enforce consistent usage of destructuring assignment of props, state, and context
  // https://eslint-react.xyz/docs/rules/prefer-destructuring-assignment
  // decision: best left up to the implementer
  '@eslint-react/prefer-destructuring-assignment': 'off',

  // Enforce importing React via a namespace import
  // https://eslint-react.xyz/docs/rules/prefer-namespace-import
  '@eslint-react/prefer-namespace-import': 'off',

  // Validates that components/hooks are pure
  // https://eslint-react.xyz/docs/rules/purity
  '@eslint-react/purity': 'error',

  // Validates correct usage of refs, not reading/writing during render
  // https://eslint-react.xyz/docs/rules/refs
  '@eslint-react/refs': 'error',

  // Enforce Rules of Hooks
  // https://eslint-react.xyz/docs/rules/rules-of-hooks
  '@eslint-react/rules-of-hooks': 'error',

  // Validates against calling setState synchronously in an effect
  // https://eslint-react.xyz/docs/rules/set-state-in-effect
  '@eslint-react/set-state-in-effect': 'error',

  // Validates against setting state during render
  // https://eslint-react.xyz/docs/rules/set-state-in-render
  '@eslint-react/set-state-in-render': 'error',

  // Validates against syntax that React does not support
  // https://eslint-react.xyz/docs/rules/unsupported-syntax
  '@eslint-react/unsupported-syntax': 'error',

  // Validates usage of useMemo with a return value
  // https://eslint-react.xyz/docs/rules/use-memo
  '@eslint-react/use-memo': 'error',

  // Ensure destructuring and symmetric naming of useState hook value and setter
  // https://eslint-react.xyz/docs/rules/use-state
  '@eslint-react/use-state': 'error',

  // --- JSX rules ---

  // Prevent passing of children as props
  // https://eslint-react.xyz/docs/rules/jsx-no-children-prop
  '@eslint-react/jsx-no-children-prop': 'error',

  // Prevent passing both children prop and JSX children simultaneously
  // https://eslint-react.xyz/docs/rules/jsx-no-children-prop-with-children
  '@eslint-react/jsx-no-children-prop-with-children': 'error',

  // Prevent accidental JS comments from being injected into JSX as text
  // https://eslint-react.xyz/docs/rules/jsx-no-comment-textnodes
  '@eslint-react/jsx-no-comment-textnodes': 'error',

  // Enforce key prop comes before spread to avoid overriding
  // https://eslint-react.xyz/docs/rules/jsx-no-key-after-spread
  '@eslint-react/jsx-no-key-after-spread': 'error',

  // Prevents unintentional leaked '$' sign before expression in JSX
  // https://eslint-react.xyz/docs/rules/jsx-no-leaked-dollar
  '@eslint-react/jsx-no-leaked-dollar': 'error',

  // Prevents unintentional leaked ';' in JSX
  // https://eslint-react.xyz/docs/rules/jsx-no-leaked-semicolon
  '@eslint-react/jsx-no-leaked-semicolon': 'error',

  // Enforce that namespaces are not used in JSX elements
  // https://eslint-react.xyz/docs/rules/jsx-no-namespace
  '@eslint-react/jsx-no-namespace': 'error',

  // Disallow unnecessary fragments
  // https://eslint-react.xyz/docs/rules/jsx-no-useless-fragment
  '@eslint-react/jsx-no-useless-fragment': 'error',

  // --- React DOM rules ---

  // Warn on usage of dangerouslySetInnerHTML
  // https://eslint-react.xyz/docs/rules/dom-no-dangerously-set-innerhtml
  '@eslint-react/dom-no-dangerously-set-innerhtml': 'error',

  // Prevent problem with children and dangerouslySetInnerHTML
  // https://eslint-react.xyz/docs/rules/dom-no-dangerously-set-innerhtml-with-children
  '@eslint-react/dom-no-dangerously-set-innerhtml-with-children': 'error',

  // Warn against using findDOMNode()
  // https://eslint-react.xyz/docs/rules/dom-no-find-dom-node
  '@eslint-react/dom-no-find-dom-node': 'error',

  // Disallow usage of flushSync
  // https://eslint-react.xyz/docs/rules/dom-no-flush-sync
  '@eslint-react/dom-no-flush-sync': 'error',

  // Disallow usage of ReactDOM.hydrate (use hydrateRoot instead)
  // https://eslint-react.xyz/docs/rules/dom-no-hydrate
  '@eslint-react/dom-no-hydrate': 'error',

  // Enforce that buttons have an explicit type attribute
  // https://eslint-react.xyz/docs/rules/dom-no-missing-button-type
  '@eslint-react/dom-no-missing-button-type': 'error',

  // Enforce sandbox attribute on iframe elements
  // https://eslint-react.xyz/docs/rules/dom-no-missing-iframe-sandbox
  '@eslint-react/dom-no-missing-iframe-sandbox': 'error',

  // Disallow usage of ReactDOM.render (use createRoot instead)
  // https://eslint-react.xyz/docs/rules/dom-no-render
  '@eslint-react/dom-no-render': 'error',

  // Disallow using ReactDOM.render return value
  // https://eslint-react.xyz/docs/rules/dom-no-render-return-value
  '@eslint-react/dom-no-render-return-value': 'error',

  // Prevent usage of javascript: URLs
  // https://eslint-react.xyz/docs/rules/dom-no-script-url
  '@eslint-react/dom-no-script-url': 'error',

  // Require style prop value be an object
  // https://eslint-react.xyz/docs/rules/dom-no-string-style-prop
  '@eslint-react/dom-no-string-style-prop': 'error',

  // Prevent usage of unknown DOM property
  // https://eslint-react.xyz/docs/rules/dom-no-unknown-property
  '@eslint-react/dom-no-unknown-property': 'error',

  // Enforce safe iframe sandbox attribute values
  // https://eslint-react.xyz/docs/rules/dom-no-unsafe-iframe-sandbox
  '@eslint-react/dom-no-unsafe-iframe-sandbox': 'error',

  // Disallow target="_blank" without rel="noreferrer"
  // https://eslint-react.xyz/docs/rules/dom-no-unsafe-target-blank
  '@eslint-react/dom-no-unsafe-target-blank': 'error',

  // Disallow usage of deprecated useFormState (use useActionState instead)
  // https://eslint-react.xyz/docs/rules/dom-no-use-form-state
  '@eslint-react/dom-no-use-form-state': 'error',

  // Prevent void DOM elements from receiving children
  // https://eslint-react.xyz/docs/rules/dom-no-void-elements-with-children
  '@eslint-react/dom-no-void-elements-with-children': 'error',

  // Enforce importing React DOM via a namespace import
  // https://eslint-react.xyz/docs/rules/dom-prefer-namespace-import
  '@eslint-react/dom-prefer-namespace-import': 'off',

  // --- RSC rules ---

  // Enforce correct function definition for React Server Components
  // https://eslint-react.xyz/docs/rules/rsc-function-definition
  '@eslint-react/rsc-function-definition': 'error',

  // --- Naming convention rules ---

  // Enforce consistent naming for React context
  // https://eslint-react.xyz/docs/rules/naming-convention-context-name
  '@eslint-react/naming-convention-context-name': 'error',

  // Enforce consistent naming for React component identifiers
  // https://eslint-react.xyz/docs/rules/naming-convention-id-name
  '@eslint-react/naming-convention-id-name': 'error',

  // Enforce consistent naming for refs
  // https://eslint-react.xyz/docs/rules/naming-convention-ref-name
  '@eslint-react/naming-convention-ref-name': 'error',

  // --- Web API rules ---

  // Prevent leaked event listeners
  // https://eslint-react.xyz/docs/rules/web-api-no-leaked-event-listener
  '@eslint-react/web-api-no-leaked-event-listener': 'error',

  // Prevent leaked setInterval calls
  // https://eslint-react.xyz/docs/rules/web-api-no-leaked-interval
  '@eslint-react/web-api-no-leaked-interval': 'error',

  // Prevent leaked ResizeObserver instances
  // https://eslint-react.xyz/docs/rules/web-api-no-leaked-resize-observer
  '@eslint-react/web-api-no-leaked-resize-observer': 'error',

  // Prevent leaked setTimeout calls
  // https://eslint-react.xyz/docs/rules/web-api-no-leaked-timeout
  '@eslint-react/web-api-no-leaked-timeout': 'error',
};
