/**
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {
  Text,
  Touchable,
  TouchableHighlight,
  TouchableNativeFeedback,
  TouchableWithoutFeedback,
  View,
  ViewProps,
} from 'react-native';
import {TestSuite} from '@rnoh/testerino';
import {createRef, useState} from 'react';
import {TestCase} from '../components';
import {useEnvironment} from '../contexts';

export const TouchablesTest = () => {
  const {
    env: {driver},
  } = useEnvironment();
  const [pressCountHighlight, setPressCountHighlight] = useState(0);
  return (
    <TestSuite name="Touchables">
      <TestCase.Logical
        itShould="export Touchable"
        fn={({expect}) => {
          expect(Touchable).to.be.not.undefined;
        }}
      />
      <TestCase.Example itShould="use cyan background on press in (TouchableHighlight)">
        <TouchableHighlight
          activeOpacity={1}
          underlayColor="cyan"
          onPress={() => {}}>
          <PressMe />
        </TouchableHighlight>
      </TestCase.Example>
      <TestCase.Example itShould="use cyan background, displayed as if pressed (TouchableHighlight)">
        <TouchableHighlight
          activeOpacity={1}
          underlayColor="cyan"
          onPress={() => {}}
          //@ts-ignore
          testOnly_pressed>
          <PressMe />
        </TouchableHighlight>
      </TestCase.Example>
      <TestCase.Example itShould="show number of presses on press in (TouchableHighlight)">
        <TouchableHighlight
          onPress={() => setPressCountHighlight(pressCountHighlight + 1)}>
          <PressMe endLabel={pressCountHighlight} />
        </TouchableHighlight>
      </TestCase.Example>
      <TestCase.Logical
        itShould="export TouchableNativeFeedback (Android only)"
        fn={({expect}) => {
          expect(TouchableNativeFeedback).to.be.not.undefined;
        }}
      />
      <TestCase.Example itShould="handle press without showing feedback">
        <TouchableWithoutFeedbackDemo />
      </TestCase.Example>
      <TestCase.Automated
        tags={['sequential']}
        itShould="handle presses on empty views"
        initialState={{
          pressed: false,
          ref: createRef<View>(),
        }}
        arrange={({setState, state, done}) => {
          return (
            <View style={{height: 100, backgroundColor: 'red'}}>
              <TouchableWithoutFeedback
                onPress={() => {
                  setState(prev => ({...prev, pressed: true}));
                  done();
                }}>
                <View ref={state.ref} style={{height: '100%', width: '100%'}} />
              </TouchableWithoutFeedback>
            </View>
          );
        }}
        act={async ({state}) => {
          await driver?.click({ref: state.ref});
        }}
        assert={({expect, state}) => {
          expect(state.pressed).to.be.true;
        }}
      />
      <TestCase.Automated
        itShould="pass when blue background is pressed"
        tags={['sequential']}
        initialState={{
          pressed: false,
          ref: createRef<View>(),
        }}
        arrange={({setState, done, state}) => (
          <View
            ref={state.ref}
            style={{
              backgroundColor: 'blue',
              alignSelf: 'center',
              position: 'relative',
            }}>
            <TouchableWithoutFeedback
              hitSlop={{top: 48, left: 48, bottom: 48, right: 48}}
              onPress={() => {
                setState((prev: any) => ({...prev, pressed: true}));
                done();
              }}>
              <View style={{width: 48, height: 48, margin: 48}} />
            </TouchableWithoutFeedback>
            <View
              style={{
                width: 48,
                height: 48,
                backgroundColor: 'red',
                position: 'absolute',
                top: 48,
                left: 48,
              }}
              onTouchEnd={e => {
                e.stopPropagation();
              }}
            />
          </View>
        )}
        act={async ({state}) => {
          await driver?.click({ref: state.ref, offset: {x: 48, y: 48}});
        }}
        assert={({expect, state}) => {
          expect(state.pressed).to.be.true;
        }}
      />
    </TestSuite>
  );
};

function TouchableWithoutFeedbackDemo() {
  const [counter, setCounter] = useState(0);
  return (
    <TouchableWithoutFeedback onPressIn={() => setCounter(prev => prev + 1)}>
      <PressMe endLabel={counter} />
    </TouchableWithoutFeedback>
  );
}

function PressMe(props: ViewProps & {endLabel?: string | number}) {
  return (
    <View {...props} style={{padding: 16, borderWidth: 1}}>
      <Text style={{color: 'blue', height: 24, width: '100%'}}>
        Press me{props.endLabel !== undefined ? ` (${props.endLabel})` : ''}
      </Text>
    </View>
  );
}