import React, { useEffect, useMemo, useRef, useState } from 'react';
import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native';
import { Calendar } from 'react-native-calendars';
import { FlatList, RefreshControl } from 'react-native-gesture-handler';
import { SafeAreaView } from 'react-native-safe-area-context';
import { ExpenseItem, LoadingSymbol, Plus, TextInputBar, Welcome } from '../../../components';
import useFetch from '../../../hooks/useFetch';

import { useRouter } from "expo-router";
import { addExpense } from "../../../services/database";
import { SimpleDate } from '../../../util/SimpleDate';
import { useTheme } from '../../contexts/ThemeContext';
import { useNavigation } from 'expo-router';
import { Category, Expense } from '../../../types/dbItems';


interface MarkingProps {
    dots?:{color:string, selectedColor?:string, key?:string}[];
    selected?: boolean;
    selectedColor?: string;
} 

type MarkedDates  = {
    [key: string]: MarkingProps;
}

interface ExpenseEntry extends Expense {
    category_name?: string;
    color?: string;
}

type Filters = {
    search?: string;
    month?: string;
    day?: string;
}

const constructMarkedDates = (data : {[column: string]: any}) => {
    let markedDates: MarkedDates = {};
    data.forEach((value: any) => {
        const dateKey: string = String(value["expense_datetime"]).split(" ")[0]

        if(markedDates[dateKey] === undefined){
            markedDates[dateKey] = {dots: []}
        }
        markedDates[dateKey].dots?.push({color: value["category_color"]})
    })
    return markedDates;
}

export default function Page() {
    const { colors, theme } = useTheme()

    const navigation = useNavigation();
    const router = useRouter();
    const [plusShow, setPlusShow] = useState(true);
    const prevOffset = useRef(0);

    const [filter, setFilter] = useState<Filters>({})

    const profile = require("../../../assets/images/profile.jpg")

    const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>)=>{
        const currentOffset = event.nativeEvent.contentOffset.y >= 0 ? event.nativeEvent.contentOffset.y : 0
        const isScrollingUp : boolean = currentOffset <= prevOffset.current;
        const isTop : boolean = currentOffset === 0
        prevOffset.current = currentOffset
        setPlusShow(isScrollingUp || isTop)
    }

    const {data, isLoading, reFetch} = useFetch({sql: "SELECT e.guid AS expense_guid, c.guid AS category_guid, e.name AS expense_name, c.name AS category_name, e.datetime AS expense_datetime, e.amount AS expense_amount, c.color AS category_color, c.type AS category_type FROM expense e JOIN category c ON e.category_guid = c.guid ORDER BY expense_datetime desc;", args: []});
    
    const expenses = useMemo<ExpenseEntry[]>(
        () => {
            console.log("expenses updated")
            return data.map((elem) => { 
                return {
                    guid: elem["expense_guid"],
                    name: elem["expense_name"],
                    amount: elem["expense_amount"],
                    dateTime: elem["expense_datetime"],
                    category_name: elem["category_name"],
                    color: elem["category_color"]}   
            })
    }, [data])

    const filteredExpenses = useMemo<ExpenseEntry[]>(
        () => {
            console.log("filter called")
            return expenses.filter((elem) => {
                if(filter.month && filter.month.substring(5, 7) !== elem.dateTime?.substring(5, 7)){
                    return false;
                }
                if(filter.day && filter.day.substring(8, 10) !== elem.dateTime?.substring(8, 10)){
                    return false;
                }
                if(filter.search && !elem.name?.toLowerCase().includes(filter.search.toLowerCase())){
                    return false;
                }
                return true;
            })
        }, [expenses, filter]
    )

    const expenseDates = useMemo(
        () => {
            let markedDates = constructMarkedDates(data)
            if(filter.day) {
                const dateKey: string = String(filter.day).split(" ")[0]
                if(markedDates[dateKey] === undefined){
                    markedDates[dateKey] = {}
                }
                markedDates[dateKey].selected = true;
                markedDates[dateKey].selectedColor = colors.accentColor;
            }
            return markedDates;
        }
    , [data, filter.day])

    useEffect(() => {
        const unsubscribe = navigation.addListener('focus', () => {
            console.log("focus event triggered")
            reFetch();
        });
        return unsubscribe;
    }, [navigation]);

    const hanldeDaySelect = (date: string | undefined) => {
        setFilter({...filter, day: date});
    }
    const handleMonthSelect = (date: string | undefined) => {
        setFilter({...filter, month: date, day: undefined});
    }
    const handleSearch = (text: string) => {
        setFilter({...filter, search: text});
    }

    console.log("rendered")
    return (
        <SafeAreaView edges={["left", "right", "top"]} style={[styles.safeAreaViewStyle, {backgroundColor: colors.containerColor}]}>
            {plusShow && <Plus onPress={()=>{
                router.push("/expense/new");

                // executeQuery({sql: "SELECT guid FROM category", args: []}).then((result) => {
                //     if("rows" in result[0]) {
                //         newExpense("Test Title", result[0]["rows"][0]["guid"], "69.69.1234", 100).then(() => {
                //             reFetch();
                //         });
                //     }
                // })
            }}/>}

            {/* {isLoading && <LoadingSymbol/>} */}
            
            <FlatList
            data={filteredExpenses}
            ListHeaderComponent={
                <>
                    <Welcome name="My Dude" image={profile} onPress={() => {router.push("/userSettings")}}/>
                        <Calendar key={theme} maxDate={SimpleDate.now().format("YYYY-MM-DD")} style={{borderRadius: 20, padding:10}} theme={{
                            dayTextColor: colors.primaryText,
                            textDisabledColor: colors.secondaryText,
                            todayTextColor: colors.accentColor,
                            calendarBackground: colors.containerColor,
                            arrowColor: colors.accentColor,
                            monthTextColor: colors.accentColor

                        }}
                        markingType='multi-dot'
                        markedDates={expenseDates}
                        onDayPress={(date) => {
                            hanldeDaySelect(date.dateString)
                        }}
                        onDayLongPress={(date) => {
                            hanldeDaySelect(undefined)
                        }}
                        onMonthChange={(date) => {
                            handleMonthSelect(date.dateString)
                        }}
                        />

                    <TextInputBar placeholder='Type to Search...' value={filter.search} onChangeText={(text) => handleSearch(text)} style={{marginBottom: 20}}></TextInputBar>
                </>
            }
            renderItem = {({item}) =>
             <ExpenseItem
                category={item.category_name!}
                color={item.color!}
                date={item.dateTime!}
                title={item.name!}
                value={String(item.amount!)}
                guid={item.guid!}
                onPress={(guid) => {router.push(`/expense/${guid}`)}}
            />}
            keyExtractor={item => item.guid!}
            ItemSeparatorComponent={() => {
                return (<View style={styles.itemSeperatorStyle}/>);
            }}
            refreshControl={
                <RefreshControl refreshing={isLoading} onRefresh={reFetch}/>
            }
            onScroll={handleScroll}
            scrollEventThrottle={20}
            />             
        </SafeAreaView> 
    );
}

const styles = StyleSheet.create({
    safeAreaViewStyle: {
        flex: 1,
        paddingHorizontal: 10
    },
    itemSeperatorStyle: {
        marginVertical: 5,
    }
});