/**
 * 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 {TestSuite} from '@rnoh/testerino';
import {Platform, ScrollView, StyleSheet, View} from 'react-native';
import React from 'react';
import {
  COMMON_PROPS,
  getScrollViewContent,
  getScrollViewContentHorizontal,
} from './fixtures';
import {useEffect, useRef, useState} from 'react';
import {Button, ObjectDisplayer, TestCase} from '../../components';

export function MiscPropsTest() {
  const rtlScrollViewRef = useRef<ScrollView>(null);
  return (
    <TestSuite name="misc props">
      <TestCase.Example itShould="scroll should be disabled" modal>
        <View style={styles.wrapperView}>
          <ScrollView {...COMMON_PROPS} scrollEnabled={false} />
        </View>
      </TestCase.Example>
      <TestCase.Example itShould="display horizontal scroll view" modal>
        <View
          style={{
            width: '100%',
            height: 150,
          }}>
          <ScrollView horizontal={true}>
            {getScrollViewContentHorizontal({})}
          </ScrollView>
        </View>
      </TestCase.Example>
      <TestCase.Example itShould="display horizontal rtl scroll view" modal>
        <View
          style={{
            width: '100%',
            height: 150,
            direction: 'rtl',
          }}>
          <ScrollView horizontal={true}>
            {getScrollViewContentHorizontal({})}
          </ScrollView>
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="scroll to end in horizontal rtl scroll view (scrollToEnd)">
        <View
          style={{
            width: '100%',
            height: 150,
            direction: 'rtl',
          }}>
          <ScrollView
            horizontal={true}
            ref={rtlScrollViewRef}
            style={{width: '100%', height: 150}}>
            {getScrollViewContentHorizontal({})}
          </ScrollView>
          <Button
            label="scroll to start"
            onPress={() => {
              rtlScrollViewRef.current?.scrollTo({x: 0, y: 0, animated: true});
            }}
          />
          <Button
            label="scroll to end"
            onPress={() => {
              rtlScrollViewRef.current?.scrollToEnd({animated: true});
            }}
          />
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="display ScrollView with the third view at the top (contentOffset)">
        <ContentOffsetTestCase />
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="scroll when contentOffset property is changed (contentOffset)">
        <ToggleContentOffsetTestCase />
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="toggle backface visibility on button press (the component should become invisible)">
        <BackfaceVisibilityTestCase />
      </TestCase.Example>
      <TestCase.Example
        modal
        skip={Platform.select({android: 'fails', harmony: 'fails on Android'})}
        itShould="display ScrollView with different contentInsets (contentInset)"
        //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/304
      >
        <View style={styles.wrapperView}>
          <ScrollView
            {...COMMON_PROPS}
            contentInset={{top: 10, right: 20, bottom: 30, left: 40}}
          />
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="display current contentHeight (onContentSizeChange)">
        <View style={{height: 500}}>
          <OnContentSizeChangeTestCase />
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="display onScroll native event throttled every second">
        <View style={{height: 500}}>
          <ObjectDisplayer
            renderContent={setObject => {
              return (
                <ScrollView
                  {...COMMON_PROPS}
                  style={{height: 300}}
                  scrollEventThrottle={1000}
                  onScroll={(e: {nativeEvent: Object}) => {
                    setObject(e.nativeEvent);
                  }}
                />
              );
            }}
          />
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="the left scrollview should decelerate faster (stops earlier) than the right one (decelarationRate)">
        <View style={[styles.wrapperView, {flexDirection: 'row'}]}>
          <ScrollView {...COMMON_PROPS} decelerationRate={0.8} />
          <ScrollView {...COMMON_PROPS} decelerationRate={0.999} />
        </View>
      </TestCase.Example>

      <TestCase.Example
        modal
        itShould="the left scrollview should bounce (briefly scroll beyond the content to show the view below and then come back to top/bottom accordingly)">
        <View style={[styles.wrapperView, {flexDirection: 'row'}]}>
          <ScrollView {...COMMON_PROPS} />
          <ScrollView {...COMMON_PROPS} bounces={false} />
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="the left scrollview should bounce (briefly scroll beyond the content to show the view below and then come back to top/bottom accordingly) (alwaysBounceVertical)">
        <View style={[styles.wrapperView, {flexDirection: 'row'}]}>
          <ScrollView
            bounces
            alwaysBounceVertical={true}
            style={COMMON_PROPS.style}
            contentContainerStyle={COMMON_PROPS.contentContainerStyle}>
            {getScrollViewContent({amountOfChildren: 2})}
          </ScrollView>
          <ScrollView
            bounces
            alwaysBounceVertical={false}
            style={COMMON_PROPS.style}
            contentContainerStyle={COMMON_PROPS.contentContainerStyle}>
            {getScrollViewContent({amountOfChildren: 2})}
          </ScrollView>
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="the top scrollview should bounce (briefly scroll beyond the content to show the view below and then come back to left/right accordingly) (alwaysBounceHorizontal)">
        <View style={[styles.wrapperView]}>
          <ScrollView
            horizontal
            bounces
            alwaysBounceHorizontal={true}
            style={COMMON_PROPS.style}
            contentContainerStyle={COMMON_PROPS.contentContainerStyle}>
            {getScrollViewContentHorizontal({amountOfChildren: 2})}
          </ScrollView>
          <ScrollView
            horizontal
            bounces
            alwaysBounceHorizontal={false}
            style={COMMON_PROPS.style}
            contentContainerStyle={COMMON_PROPS.contentContainerStyle}>
            {getScrollViewContentHorizontal({amountOfChildren: 2})}
          </ScrollView>
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        skip={Platform.select({android: 'fails', harmony: 'fails on Android'})}
        itShould="scroll outside of the content when pressing the button (scrollToOverflowEnabled)"
        //https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/315
      >
        <ScrollToOverflowEnabledTestCase />
      </TestCase.Example>
      <TestCase.Example
        modal
        skip={'https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/312'}
        itShould="the left scrollview should allow for nested scroll while the right one shouldn't (nestedScrollEnabled)">
        <View
          style={[
            styles.wrapperView,
            {flexDirection: 'row', alignContent: 'space-between'},
          ]}>
          <ScrollView {...COMMON_PROPS}>
            <ScrollView
              nestedScrollEnabled
              style={{
                width: '70%',
                height: 200,
                borderColor: 'firebrick',
                borderWidth: 2,
              }}>
              {getScrollViewContent({
                style: {backgroundColor: 'green'},
                amountOfChildren: 5,
              })}
            </ScrollView>
            {getScrollViewContent({})}
          </ScrollView>
          <ScrollView {...COMMON_PROPS}>
            <ScrollView
              nestedScrollEnabled={false}
              style={{
                width: '70%',
                height: 200,
                borderColor: 'firebrick',
                borderWidth: 2,
              }}>
              {getScrollViewContent({
                style: {backgroundColor: 'green'},
                amountOfChildren: 5,
              })}
            </ScrollView>
            {getScrollViewContent({})}
          </ScrollView>
        </View>
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="scroll down on the btn press, but prevent scrolling by dragging (scrollEnabled)">
        <ScrollEnabledTestCase />
      </TestCase.Example>
      <TestCase.Example
        modal
        skip={'https://gl.swmansion.com/rnoh/react-native-harmony/-/issues/499'}
        itShould="render scroll view with different fading edge length (fadingEdgeLength)">
        <ScrollViewFadingEdgeLengthTest />
      </TestCase.Example>
      <TestCase.Example
        modal
        itShould="display vertical scroll view when alwaysBounceHorizontal set to true">
        <View
          style={[
            styles.wrapperView,
            {flexDirection: 'row', alignContent: 'space-between'},
          ]}>
          <ScrollView {...COMMON_PROPS} alwaysBounceHorizontal={true}>
            {getScrollViewContent({})}
          </ScrollView>
        </View>
      </TestCase.Example>
    </TestSuite>
  );
}

function ScrollEnabledTestCase() {
  const scrollRef = React.useRef<ScrollView>(null);
  return (
    <View style={styles.wrapperView}>
      <Button
        label={'Scroll To offset y 150'}
        onPress={() => {
          scrollRef.current?.scrollTo({x: 0, y: 150, animated: false});
        }}
      />
      <ScrollView style={{flex: 1}} scrollEnabled={false} ref={scrollRef}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function ScrollToOverflowEnabledTestCase() {
  const ref = useRef<ScrollView>(null);
  return (
    <View style={styles.wrapperView}>
      <Button
        label={'Scroll outside of the content'}
        onPress={() => {
          ref.current?.scrollTo({x: 0, y: -60, animated: true});
        }}
      />
      <ScrollView scrollToOverflowEnabled={true} ref={ref}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}
function OnContentSizeChangeTestCase() {
  const [amountOfChildren, setAmountOfChildren] = useState(3);
  return (
    <ObjectDisplayer
      renderContent={setObject => {
        return (
          <View style={{width: '100%', height: '70%'}}>
            <Button
              label={'Add one more item'}
              onPress={() => {
                setAmountOfChildren(amountOfChildren + 1);
              }}
            />
            <ScrollView
              onContentSizeChange={(_, contentHeight) => {
                setObject({contentHeight});
              }}>
              {getScrollViewContent({amountOfChildren: amountOfChildren})}
            </ScrollView>
          </View>
        );
      }}
    />
  );
}

function ContentOffsetTestCase() {
  return (
    <View style={styles.wrapperView}>
      <ScrollView
        style={{
          ...styles.wrapperView,
        }}
        contentOffset={{x: 0, y: 100}}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function ToggleContentOffsetTestCase() {
  const [contentOffset, setContentOffset] = useState(100);
  useEffect(() => {
    const id = setInterval(() => {
      setContentOffset(prev => (prev + 50) % 200);
    }, 1000);
    return () => {
      clearInterval(id);
    };
  }, []);

  return (
    <View style={styles.wrapperView}>
      <ScrollView
        style={{
          ...styles.wrapperView,
        }}
        contentOffset={{x: 0, y: contentOffset}}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function BackfaceVisibilityTestCase() {
  const [backfaceVisibility, setBackfaceVisibility] = useState(true);

  return (
    <View style={styles.wrapperView}>
      <Button
        label={`Make backface ${backfaceVisibility ? 'invisible' : 'visible'}`}
        onPress={() => {
          setBackfaceVisibility(!backfaceVisibility);
        }}
      />
      <ScrollView
        style={{
          ...styles.wrapperView,
          backfaceVisibility: backfaceVisibility ? 'visible' : 'hidden',
          transform: [{rotateX: '180deg'}],
        }}>
        {getScrollViewContent({})}
      </ScrollView>
    </View>
  );
}

function ScrollViewFadingEdgeLengthTest() {
  return (
    <View
      style={{
        width: '100%',
        justifyContent: 'center',
        backgroundColor: 'blue',
      }}>
      <View
        style={{
          height: 400,
          marginTop: 50,
          marginBottom: 50,
        }}>
        <ScrollView fadingEdgeLength={100}>
          {getScrollViewContent({})}
        </ScrollView>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  wrapperView: {
    height: 300,
    width: '60%',
  },
});