import {
    Button,
    Card, CardContent,
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    Divider,
    List, ListItemText,
    Snackbar,
    Stack,
    Typography,
    useTheme
} from "@mui/material";
import { useMutation, useQuery } from "@tanstack/react-query";
import React, { PropsWithChildren, useEffect, useState } from "react";
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { useTranslation } from "react-i18next";
import OrderType, { OrderPatch, OrderStatusEnum } from "../../components/Order";
import { useAccount } from "../AccountProvider";
import { fetchOrdersAdmin, orderPatch } from "../query/Queries";

// The order in which the statuses are displayed
const statusOrder: OrderStatusEnum[] = [
    OrderStatusEnum.CANCELLED,
    OrderStatusEnum.ISSUES,
    OrderStatusEnum.ORDERED,
    OrderStatusEnum.IN_PROGRESS,
    OrderStatusEnum.DELIVERED
];


const OrderCard: React.FC<{ order: OrderType; onClick: () => void }> = ({ order, onClick }) => {

    const { t } = useTranslation();

    const [{ isDragging }, drag] = useDrag(() => ({
        type: 'order',
        item: { id: order.id },
        collect: (monitor) => ({
            isDragging: !!monitor.isDragging(),
        }),
    }));

    return (
        <div ref={drag} style={{ opacity: isDragging ? 0.5 : 1, marginBottom: 8 }}>
            <Card elevation={4}>
                <CardContent onClick={onClick}>
                    <Typography gutterBottom variant="h5" component="div">
                        Order:   {order.id}
                    </Typography>
                    <Typography>
                        {t('date') + ": " + new Date(order.time).toUTCString()}
                    </Typography>
                    <Typography>
                        {t('total') + ": " + order.total}
                    </Typography>
                </CardContent>
            </Card>
        </div>
    );
};

const Column: React.FC<PropsWithChildren<{ status: OrderStatusEnum; onDrop: (id: number, status: OrderStatusEnum) => void }>> = ({ status, onDrop, children }) => {

    const { t } = useTranslation();
    const theme = useTheme();

    const [{ isOver }, drop] = useDrop(() => ({
        accept: 'order',
        drop: (item: { id: number }) => onDrop(item.id, status),
        collect: (monitor) => ({
            isOver: !!monitor.isOver(),
        }),
    }));

    return (
        <div ref={drop} style={{ flex: 1, backgroundColor: isOver ? theme.palette.background.paper : 'transparent', padding: 1 }}>
            <Card sx={{ minHeight: '100%', marginTop: 2, marginLeft: 1 }} elevation={4}>
                <CardContent>
                    <Typography variant="h6">{t(status)}</Typography>
                    {children}
                </CardContent>
            </Card>
        </div>
    );
};

const EditOrder: React.FC<{ open: boolean; order: OrderType | null; onClose: () => void }> = ({ open, order, onClose }) => {

    const { t } = useTranslation();
    if (order === null)
        return "";
    return (
        <Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
            <DialogTitle>
                {`${t(order.status)} #${order?.id}`}
            </DialogTitle>
            <DialogContent dividers>
                {order && (
                    <Stack spacing={2}>
                        <Typography variant="subtitle1">{`${t('orderDate')}: ${new Date(order.time).toDateString()}`}</Typography>
                        <Divider />
                        <Typography variant="subtitle2">{t('orderedItems')}:</Typography>
                        <List dense>
                            {order.orderItems.map((item, idx) => (
                                <ListItemText
                                    key={idx}
                                    primary={`${item.article} x${item.amount}`}
                                />
                            ))}
                        </List>
                        <Divider />
                        <Typography variant="h6">{`${t('sum')}: ${(order.total / 100).toFixed(2)} €`}</Typography>
                    </Stack>
                )}
            </DialogContent>
            <DialogActions>
                <Button onClick={onClose}>{t('close')}</Button>
            </DialogActions>
        </Dialog>
    );
};

// Main component for managing orders
export default function OrdersInfo() {
    const [orders, setOrders] = useState<OrderType[]>([]);
    const [editOrder, setEditOrder] = useState<OrderType | null>(null);
    const [openSnackbar, setOpenSnackbar] = useState(false);

    const { user: loginData } = useAccount();

    const { data, refetch } = useQuery({
        queryKey: ["fetchOrdersAdmin", loginData],
        queryFn: () => fetchOrdersAdmin(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }),
        retry: 3,
        retryDelay: 1000,
    });

    const patchOrderMutation = useMutation({
        mutationFn: (order: OrderPatch) =>
            orderPatch({ id: order.id, status: order.status }),
    });


    useEffect(() => {
        console.log("data", data);
        if (data) {
            setOrders(data);
        }
    }, [data]);

    const handleDrop = async (id: number, status: OrderStatusEnum) => {
        const obj = orders.find((o) => o.id === id);
        if (!obj) {
            setOpenSnackbar(true);
            return;
        }
        try {
            await patchOrderMutation.mutateAsync({ id: obj.id, status: status });
            refetch();
            setOrders(orders.map((o) => (o.id === id ? { ...o, status } : o)));
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        } catch (error) {
            setOpenSnackbar(true);
        }
    };
    const handleEdit = (order: OrderType) => setEditOrder(order);

    return (
        <DndProvider backend={HTML5Backend}>
            <div style={{ display: 'flex', gap: 10, minHeight: '90%' }}>
                {statusOrder.map((status) => (
                    <Column key={status} status={status} onDrop={handleDrop}>
                        {orders
                            .filter((o) => o.status === status)
                            .map((o) => (
                                <OrderCard key={o.id} order={o} onClick={() => handleEdit(o)} />
                            ))}
                    </Column>
                ))}
            </div>
            <EditOrder
                open={!!editOrder}
                order={editOrder}
                onClose={() => setEditOrder(null)}
            />
            <Snackbar
                open={openSnackbar}
                autoHideDuration={4000}
                onClose={() => setOpenSnackbar(false)}
                message="Failed changing Orderstatus"
            />
        </DndProvider>
    );

}
