/**
 * 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 {
  ScrollView,
  Text,
  TouchableOpacity,
  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 TouchableOpacityTest = () => {
  const [pressCountOpacity, setPressCountOpacity] = useState(0);
  const [onLayoutTestText, setOnLayoutTestText] = useState('');
  const {
    env: {driver},
  } = useEnvironment();
  return (
    <TestSuite name="TouchableOpacity">
      <TestCase.Example itShould="make the text less visible on press">
        <TouchableOpacity onPress={() => {}}>
          <PressMe />
        </TouchableOpacity>
      </TestCase.Example>
      <TestCase.Example itShould="make the text slightly less visible on press (activeOpacity)">
        <TouchableOpacity activeOpacity={0.5} onPress={() => {}}>
          <PressMe />
        </TouchableOpacity>
      </TestCase.Example>
      <TestCase.Example itShould="show number of presses on press">
        <TouchableOpacity
          onPress={() => setPressCountOpacity(pressCountOpacity + 1)}>
          <PressMe endLabel={pressCountOpacity} />
        </TouchableOpacity>
      </TestCase.Example>
      <TestCase.Example itShould="render disabled">
        <TouchableOpacity disabled>
          <PressMe endLabel={'disabled'} />
        </TouchableOpacity>
      </TestCase.Example>
      <TestCase.Example itShould="show layout data onLayout">
        <TouchableOpacity
          onLayout={event => {
            setOnLayoutTestText(JSON.stringify(event.nativeEvent.layout));
          }}>
          <PressMe style={{height: 100}} endLabel={onLayoutTestText} />
        </TouchableOpacity>
      </TestCase.Example>
      <TestCase.Example itShould="show square (red background, white border, rounded corners)">
        <TouchableOpacity
          style={{
            backgroundColor: 'rgb(255, 0, 0)',
            width: 100,
            height: 100,
            borderWidth: 3,
            borderColor: 'white',
            borderTopLeftRadius: 10,
            borderTopRightRadius: 20,
            borderBottomRightRadius: 30,
            borderBottomLeftRadius: 40,
          }}>
          <PressMe />
        </TouchableOpacity>
      </TestCase.Example>
      <TestCase.Automated
        itShould="Gray square does not trigger onPress when pressed and dragged; pink square does not trigger onScroll."
        tags={['sequential']}
        initialState={{
          pressIn: 0,
          pressed: 0,
          scrolled: 0,
          ref: createRef<React.ElementRef<typeof View>>(),
        }}
        arrange={({state, setState, done}) => {
          return (
            <ScrollViewNestedInTouchableOpacity
              draggingTargetRef={state.ref}
              onTouchableOpacityPressIn={() => {
                setState(prev => ({...prev, pressIn: prev.pressIn + 1}));
              }}
              onParentTouchableOpacityPress={() => {
                setState(prev => ({...prev, pressed: prev.pressed + 1}));
              }}
              onFinishedDragging={() => {
                setState(prev => ({...prev, scrolled: prev.scrolled + 1}));
                done();
              }}
            />
          );
        }}
        act={async ({state}) => {
          await driver?.swipe({
            ref: state.ref,
            fromOffset: {x: 60, y: 0},
            toOffset: {x: 0, y: 0},
          });
          await driver?.swipe({
            ref: state.ref,
            fromOffset: {x: 0, y: 0},
            toOffset: {x: -100, y: 0},
          });
        }}
        assert={({expect, state}) => {
          expect(state.pressIn).to.be.eq(1);
          expect(state.pressed).to.be.eq(1);
          expect(state.scrolled).to.be.eq(1);
        }}
      />
    </TestSuite>
  );
};

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

function ScrollViewNestedInTouchableOpacity(props: {
  onParentTouchableOpacityPress: () => void;
  onTouchableOpacityPressIn: () => void;
  onFinishedDragging: () => void;
  draggingTargetRef: React.Ref<View>;
}) {
  return (
    <TouchableOpacity
      style={{backgroundColor: 'pink'}}
      onPress={() => {
        props.onParentTouchableOpacityPress();
      }}>
      <ScrollView
        horizontal
        showsHorizontalScrollIndicator={false}
        onScrollEndDrag={() => {
          setTimeout(() => {
            props.onFinishedDragging();
          }, 100);
        }}>
        <View
          style={{
            flex: 1,
            justifyContent: 'center',
            flexDirection: 'row',
          }}>
          {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(value => {
            return (
              <TouchableOpacity
                ref={value === 1 ? props.draggingTargetRef : undefined}
                key={value}
                onPressIn={() => props.onTouchableOpacityPressIn()}
                style={{
                  width: 64,
                  height: 64,
                  marginRight: 64,
                  backgroundColor: '#ddddd' + value,
                }}>
                <Text>
                  {value}
                  {value === 1 ? ' (target)' : ''}
                </Text>
              </TouchableOpacity>
            );
          })}
        </View>
      </ScrollView>
    </TouchableOpacity>
  );
}