import React, { useEffect, useState } from "react";
import { Keyboard } from "react-native";
import Animated, {
  Easing,
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from "react-native-reanimated";
import { useQuery } from "@tanstack/react-query";
import { View, ZStack } from "tamagui";

import { getMediaPoster, searchTitle } from "@movie-web/tmdb";

import type { ItemData } from "~/components/item/item";
import Item from "~/components/item/item";
import ScreenLayout from "~/components/layout/ScreenLayout";
import { SearchBar } from "~/components/ui/Searchbar";

export default function SearchScreen() {
  const [query, setQuery] = useState("");
  const translateY = useSharedValue(0);
  const fadeAnim = useSharedValue(1);
  const searchResultsOpacity = useSharedValue(0);
  const searchResultsScale = useSharedValue(0.95);
  const [searchResultsLoaded, setSearchResultsLoaded] = useState(false);

  const { data } = useQuery({
    queryKey: ["searchResults", query],
    queryFn: () => fetchSearchResults(query),
  });

  useEffect(() => {
    if (data && data.length > 0 && query) {
      searchResultsOpacity.value = withTiming(1, { duration: 500 });
      searchResultsScale.value = withTiming(1, { duration: 500 });
      setSearchResultsLoaded(true);
    } else if (!query) {
      searchResultsOpacity.value = withTiming(0, { duration: 500 });
      searchResultsScale.value = withTiming(0.95, { duration: 500 });
      setSearchResultsLoaded(false);
    }
  }, [data, query, searchResultsOpacity, searchResultsScale]);

  useEffect(() => {
    const keyboardWillShowListener = Keyboard.addListener(
      "keyboardWillShow",
      (e) => {
        translateY.value = withTiming(
          -(e.endCoordinates.height - 100), // determines the height of the Searchbar above keyboard, use Platform.select to adjust value if needed
          {
            duration: e.duration ?? 250, // duration always returns 0 on Android, adjust value if needed
            easing: Easing.out(Easing.ease),
          },
        );
      },
    );

    const keyboardWillHideListener = Keyboard.addListener(
      "keyboardWillHide",
      () => {
        translateY.value = withTiming(0, {
          duration: 250,
          easing: Easing.out(Easing.ease),
        });
      },
    );

    return () => {
      keyboardWillShowListener.remove();
      keyboardWillHideListener.remove();
    };
  }, [translateY]);

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ translateY: translateY.value }],
      opacity: fadeAnim.value,
    };
  });

  const searchResultsStyle = useAnimatedStyle(() => {
    return {
      opacity: searchResultsOpacity.value,
      transform: [{ scale: searchResultsScale.value }],
    };
  });

  const handleScrollBegin = () => {
    fadeAnim.value = withTiming(0, {
      duration: 100,
    });
  };

  const handleScrollEnd = () => {
    fadeAnim.value = withTiming(1, {
      duration: 100,
    });
  };

  return (
    <ZStack flex={1}>
      <ScreenLayout
        onScrollBeginDrag={handleScrollBegin}
        onMomentumScrollEnd={handleScrollEnd}
        scrollEnabled={searchResultsLoaded ? true : false}
        keyboardDismissMode="on-drag"
        keyboardShouldPersistTaps="handled"
        contentContainerStyle={{ flexGrow: 1 }}
      >
        <View>
          <Animated.View style={[searchResultsStyle, { flex: 1 }]}>
            <View flexDirection="row" flexWrap="wrap">
              {data?.map((item, index) => (
                <View
                  key={index}
                  paddingHorizontal={12}
                  paddingBottom={12}
                  width="50%"
                >
                  <Item data={item} />
                </View>
              ))}
            </View>
          </Animated.View>
        </View>
      </ScreenLayout>
      <Animated.View
        style={[
          {
            position: "absolute",
            bottom: 5,
            left: 0,
            right: 0,
          },
          animatedStyle,
        ]}
      >
        <SearchBar onSearchChange={setQuery} />
      </Animated.View>
    </ZStack>
  );
}

async function fetchSearchResults(query: string): Promise<ItemData[]> {
  const results = await searchTitle(query);

  return results.map((result) => ({
    id: result.id.toString(),
    title: result.media_type === "tv" ? result.name : result.title,
    posterUrl: getMediaPoster(result.poster_path),
    release_date: new Date(
      result.media_type === "tv" ? result.first_air_date : result.release_date,
    ),
    year: new Date(
      result.media_type === "tv" ? result.first_air_date : result.release_date,
    ).getFullYear(),
    type: result.media_type,
  }));
}
