import {useDispatch, useSelector} from "react-redux";
import {RootState, useAppDispatch} from "../../redux/store";
import {ASSEMBLY_STATE} from "../../types/assembly";
import {StyleSheet, Text, View} from "react-native";
import BasicButton, {BasicButtonProps} from "../../components/BasicButton/BasicButton";
import {BaseButton} from "react-native-gesture-handler";
import {
    confirmAssembly, endAssembly,
    openAcceptModal,
    selectProduct,
    setAssembled,
    skipCrpt
} from "../../features/assembly/assemblySlice";
import {useScanningContext} from "../../providers/ScanProvider";
import assemblyApi from "../../api/assemblyApi";
import {OkMessageResponse} from "../../types/api";
import Toast from "react-native-toast-message";
import {useEffect, useState} from "react";
import {RFPercentage} from "react-native-responsive-fontsize";
import {responsiveHeight} from "react-native-responsive-dimensions";
import {closeLoadingModal, openLoadingModal, setLoadingText} from "../../features/loadingModal/loadingModalSlice";
import printingService from "../../utils/PrintingService";
import printingApi from "../../api/printingApi";
import {setPrinterName} from "../../features/printing/printingSlice";
import {openReprintModal} from "../../features/reprintModal/reprintModalSlice";
import {showReward} from "../../features/animations/animationsSlice";
import {fetchBalance, refreshTransactions} from "../../features/balance/balanceSlice";
import {NavigationProp, useNavigation} from "@react-navigation/native";
import {TabNavigatorParamList} from "../MainScreen/MainScreen";


const AssemblyButton = (props: BasicButtonProps) => {
    return (
        <BasicButton
            {...props}
            containerStyle={{flex: 1}}
        />
    )
}
const NotStartedButtons = () => {
    const dispatch = useDispatch();
    const onStartAssembly = () => {
        dispatch(openAcceptModal());
    }
    return (
        <AssemblyButton
            label={"Начать сборку"}
            onPress={onStartAssembly}
        />
    )

}

const ScanningCrptButtons = () => {
    const dispatch = useAppDispatch();

    const state = useSelector((state: RootState) => state.assembly);
    const [isInitialized, setIsInitialized] = useState(false);
    const getNeedState = () => {
        if (!state.order) return {};
        return state.order.products.reduce((acc, product) => {
            acc[product.databaseId] = false;
            return acc;
        }, {} as { [key: number]: boolean })
    }

    const [crptNeedState, setCrptNeedState] = useState<{ [key: number]: boolean }>(getNeedState());
    const {scan} = useScanningContext();
    const onAttached = (response: OkMessageResponse) => {

        Toast.show({
            type: response.ok ? "success" : "error",
            text1: "Сканирование честного знака",
            text2: response.message,
        });

        if (!response.ok) return

        setCrptNeedState(prevState => {
            if (!state.selectedProduct) return prevState;
            return {...prevState, [state.selectedProduct.databaseId]: false}

        })
    }
    const onScanned = (data: string) => {
        if (!state.selectedProduct) return;
        assemblyApi.attachCrpt(state.selectedProduct.databaseId, data).then(onAttached);
    }
    const onScanClick = () => {
        scan({callback: onScanned});
    }
    const initialize = async () => {
        dispatch(setLoadingText('Проверка необходимости сканирования честного знака...'))
        dispatch(openLoadingModal());
        if (!state.order) return;
        const responses = await Promise.all(state.order.products.map(async (product) => {
            const response = await assemblyApi.needCrpt(product.databaseId);
            return {productId: product.databaseId, need: response.needCrpt};
        }));
        // update state
        setCrptNeedState(responses.reduce((acc, {productId, need}) => {
            acc[productId] = need;
            return acc;
        }, {} as { [key: number]: boolean }));

        setIsInitialized(true);
        dispatch(closeLoadingModal());
        ////
        ////
        dispatch(selectProduct(0))
    }
    useEffect(() => {
        if (!isInitialized) return;
        if (Object.values(crptNeedState).every(value => !value))
            dispatch(skipCrpt())
    }, [crptNeedState]);

    useEffect(() => {
        initialize();
    }, []);
    return (
        <>
            <AssemblyButton
                disabled={!state.selectedProduct || !crptNeedState[state.selectedProduct.databaseId]}
                onPress={onScanClick}
                label={"Сканировать честный знак"}
            />
            <AssemblyButton
                onPress={() => {
                    dispatch(skipCrpt())
                }}
                label={"Пропустить"}
            />
        </>
    )
}

const AssemblingButtons = () => {
    const dispatch = useAppDispatch();
    const state = useSelector((state: RootState) => state.assembly);
    useEffect(() => {
        dispatch(selectProduct(0));
    }, []);
    return (
        <AssemblyButton
            disabled={state.selectedProduct?.assembled}
            onPress={() => {
                if (!state.selectedProduct) return;
                dispatch(setAssembled({orderProductId: state.selectedProduct.databaseId}));
            }}
            label={"Отметить как собранный"}
        />
    )
}

const AllProductsAssembledButtons = () => {
    const dispatch = useAppDispatch();
    const state = useSelector((state: RootState) => state.assembly);

    const [skipButtonVisible, setSkipButtonVisible] = useState(false);

    const onConfirmClick = () => {
        if (!state.assembly) return;
        dispatch(setLoadingText('Подтверждение сборки...'))
        dispatch(openLoadingModal());
        assemblyApi.confirm(state.assembly.databaseId).then(({ok, message}) => {
            dispatch(closeLoadingModal());
            Toast.show({
                type: ok ? 'success' : 'error',
                text1: 'Подтверждение сборки',
                text2: message
            })
            if (ok) {
                dispatch(confirmAssembly());
            } else {
                setSkipButtonVisible(true);
            }
        })
    }
    const onSkipClick = () => {
        dispatch(confirmAssembly());
    }
    return (
        <>
            <AssemblyButton label={"Подтвердить сборку"} onPress={onConfirmClick}/>
            {skipButtonVisible && <AssemblyButton label={"Пропустить"} onPress={onSkipClick}/>}
        </>
    )

}

const ConfirmedButtons = () => {
    const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Barcode'>>();

    const dispatch = useAppDispatch();
    const order = useSelector((state: RootState) => state.assembly.order);
    const assembly = useSelector((state: RootState) => state.assembly.assembly);
    const onPrintLabel = () => {
        if (!order) return;
        let printer = printingService.getInstance().getPrinter(order.baseMarketplace);
        dispatch(setLoadingText('Идет печать этикетки...'))
        dispatch(openLoadingModal())
        printingApi.getLabel(order.databaseId).then(pdfData => {
            printingService.getInstance().printPdf(printer, pdfData).then((response) => {
                dispatch(closeLoadingModal());
                if (response) return;
                dispatch(setPrinterName({printerName: printer}));
                dispatch(openReprintModal());
            });
        })
    }
    const onEndAssembly = () => {
        if (!assembly) return;
        assemblyApi.close(assembly.databaseId).then(({ok, message, reward}) => {
            Toast.show({
                type: ok ? 'success' : 'error',
                text1: 'Завершение сборки',
                text2: message
            });
            if (ok) {
                dispatch(showReward({reward}));
                dispatch(fetchBalance())
                dispatch(refreshTransactions())
            }
            dispatch(endAssembly());
            navigator.navigate('Barcode');
        })
    }
    useEffect(() => {
        onPrintLabel();
    }, []);
    return (<>
        <AssemblyButton
            onPress={onPrintLabel}
            label={"Печать этикетки"}/>
        <AssemblyButton
            onPress={onEndAssembly}
            label={"Завершить сборку"}/>
    </>)

}

const EndedButtons = () => {
    return (<></>)

}

const AssemblyControls = () => {
    const state = useSelector((state: RootState) => state.assembly);
    const getButtons = () => {
        if (state.localState === undefined) return (<BasicButton
            label={"Ошибка"}
            disabled={true}
        />)

        switch (state.localState) {
            case ASSEMBLY_STATE.NOT_STARTED:
                return <NotStartedButtons/>
            case ASSEMBLY_STATE.SCANNING_CRPT:
                return <ScanningCrptButtons/>
            case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
                return <AssemblingButtons/>
            case ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED:
                return <AllProductsAssembledButtons/>
            case ASSEMBLY_STATE.CONFIRMED:
                return <ConfirmedButtons/>
            case ASSEMBLY_STATE.ENDED:
                return <EndedButtons/>
        }
    }
    return (<>{getButtons()}</>)
}

const styles = StyleSheet.create({
    buttonsContainer: {
        backgroundColor: "white",
        padding: RFPercentage(2),
        flex: 0.5,
        borderRadius: RFPercentage(3),
        rowGap: responsiveHeight(2)
    },
})
export default AssemblyControls;